如何从字符串发送带有 CSV 附件的电子邮件


How to send an email with a CSV attachment from a string

这是我的尝试,你能告诉我我做错了什么吗?

Allputcsv 将数组转换为 CSV 格式的字符串。然后是base64编码和块拆分,这似乎适用于普通文件,但是由于我使用的是字符串,我应该做些什么不同的事情吗?

<?php
function sputcsv($row, $delimiter = ',', $enclosure = '"', $eol = "'n")
{
    static $fp = false;
    if ($fp === false)
    {
        $fp = fopen('php://temp', 'r+');
    }
    else
    {
        rewind($fp);
    }
    if (fputcsv($fp, $row, $delimiter, $enclosure) === false)
    {
        return false;
    }
    rewind($fp);
    $csv = fgets($fp);
    if ($eol != PHP_EOL)
    {
        $csv = substr($csv, 0, (0 - strlen(PHP_EOL))) . $eol;
    }
    return $csv;
}
function allputcsv($arr) {
    $str = "";
    foreach($arr as $val) {
        $str .= sputcsv($val);
    }
    return $str;
}
function send_mail($arr) {
    $to = 'youraddress@example.com'; 
    $subject = 'Test email with attachment'; 
    $random_hash = md5(date('r', time())); 
    $headers = "From: webmaster@example.com'r'nReply-To: webmaster@example.com"; 
    $headers .= "'r'nContent-Type: multipart/mixed; boundary='"--".$random_hash."'""; 
    $attachment = chunk_split(base64_encode(allputcsv($arr))); 
    ob_start();
    ?> 
    --<?php echo $random_hash; ?>  
    Content-Type: text/plain; charset=ISO-8859-1; format=flowed
    Content-Transfer-Encoding: 7bit
    Hello World!!! 
    This is simple text email message. 
    --<?php echo $random_hash; ?>  
    Content-Type: application/vnd.ms-excel;
     name="test.csv"
    Content-Transfer-Encoding: base64
    Content-Disposition: attachment;
     filename="test.csv"
    <?php echo $attachment; ?> 
    --<?php echo $random_hash; ?>-- 
    <?php 
    $message = ob_get_clean(); 
    $mail_sent = @mail( $to, $subject, $message, $headers ); 
}
$array = array(array(1,2,3,4,5,6,7),array(1,2,3,4,5,6,7),array(1,2,3,4,5,6,7));
send_mail($array);
?>

注意:我必须使用我别无选择的邮件功能(我可以使用包装器,但我不想这样做),并且我无法将文件保存在服务器端。

您可以以更短、更高效的方式轻松地将 CSV 创建代码包装到单个函数中。

CSV 文件的正确 MIME 类型是 text/csv 。此外,您应该使用字符串连接和显式'r'n序列,因为 RFC 要求 CRLF 行分隔,并且通过使用带有文字新行的 heredoc/nowdoc/output 缓冲,您最终会遇到 2 个问题:

  1. 缩进可能会搞砸消息格式
  2. 在 ASCII 模式下通过 FTP 复制文件可能会中断行尾

试试这个:

function create_csv_string($data) {
  // Open temp file pointer
  if (!$fp = fopen('php://temp', 'w+')) return FALSE;
  // Loop data and write to file pointer
  foreach ($data as $line) fputcsv($fp, $line);
  // Place stream pointer at beginning
  rewind($fp);
  // Return the data
  return stream_get_contents($fp);
}
function send_csv_mail ($csvData, $body, $to = 'youraddress@example.com', $subject = 'Test email with attachment', $from = 'webmaster@example.com') {
  // This will provide plenty adequate entropy
  $multipartSep = '-----'.md5(time()).'-----';
  // Arrays are much more readable
  $headers = array(
    "From: $from",
    "Reply-To: $from",
    "Content-Type: multipart/mixed; boundary='"$multipartSep'""
  );
  // Make the attachment
  $attachment = chunk_split(base64_encode(create_csv_string($csvData))); 
  // Make the body of the message
  $body = "--$multipartSep'r'n"
        . "Content-Type: text/plain; charset=ISO-8859-1; format=flowed'r'n"
        . "Content-Transfer-Encoding: 7bit'r'n"
        . "'r'n"
        . "$body'r'n"
        . "--$multipartSep'r'n"
        . "Content-Type: text/csv'r'n"
        . "Content-Transfer-Encoding: base64'r'n"
        . "Content-Disposition: attachment; filename='"file.csv'"'r'n"
        . "'r'n"
        . "$attachment'r'n"
        . "--$multipartSep--";
   // Send the email, return the result
   return @mail($to, $subject, $body, implode("'r'n", $headers)); 
}
$array = array(array(1,2,3,4,5,6,7), array(1,2,3,4,5,6,7), array(1,2,3,4,5,6,7));
send_csv_mail($array, "Hello World!!!'r'n This is simple text email message.");

这是一个更简单的解决方案,用于创建我用来使用 phpmailer 通过电子邮件发送附件的 csv。

$csvinfo .= "$row[0],$row[1],$row[2],$row[3]'n";
$attachment = "details.csv";  
file_put_contents($attachment, $csvinfo, LOCK_EX);

以及相关的 phpmailer 行,以发送带有附件的电子邮件

$mail = new PHPMailer;
$mail->isSMTP();             // Set mailer to use SMTP
$mail->Host = 'x';           // Specify main and backup SMTP servers
$mail->SMTPAuth = true;       // Enable SMTP     authentication
$mail->Username = 'xx';       // SMTP username
$mail->Password = 'xx';         // SMTP password
$mail->SMTPSecure = 'tls';     // Enable TLS or SSL also accepted
$mail->Port = 587;               // TCP port to connect to
$mail->setFrom('me@madein.us', 'Lily');
$mail->AddAddress("you@madein.us");
$mail->addAttachment($attachment);         // Add attachments
$mail->isHTML(true);             // Set email format to HTML
$mail->Subject = "Report";
$mail->Body    = $message;
if(!$mail->send()) {
    echo 'Message could not be sent.';
    echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
    echo 'Message has been sent';
}

你可以试试这段代码。它工作完美。

<?php
$con = mysqli_connect('localhost', 'username', 'password', 'databasename');
if (!$con)
{
    die("error" . mysqli_connect_error());
}
error_reporting(E_ERROR);
$filename = "menu_list";
$sql = mysqli_query($con, "SELECT * FROM menu_list");
$row = mysqli_fetch_assoc($sql);
$filename2='datas/'.$filename.'.csv';
$fp = fopen($filename2, "w");
$seperator = "";
$comma = "";
foreach ($row as $name => $value){$seperator .= $comma . '' . str_replace('', '""', $name);$comma = ",";}
$seperator .= "'n";
$seperator;
fputs($fp, $seperator);
mysqli_data_seek($sql, 0);
while ($row = mysqli_fetch_assoc($sql))
{
    $seperator = "";
    $comma = "";
    foreach ($row as $name => $value){$seperator .= $comma . '' . str_replace('', '""', $value);$comma = ",";}
    $seperator .= "'n";
    fputs($fp, $seperator);
}
fclose($fp);
$my_file = $filename2;
$path = "datas/";
$from_name = "solomon";
$from_mail = "pss@gmail.com";
$mailto = "pssworkcse@gmail.com";
$subject = "This is a mail with attachment.";
$message = "Hi,'r'n do you got attachment?'r'n'r'Solomon";
$replyto = "pssworkcse@gmail.com";
$file = $my_file;
$file_size = filesize($file);
$handle = fopen($file, "r");
$content = fread($handle, $file_size);
fclose($handle);
$content = chunk_split(base64_encode($content));
$uid = md5(uniqid(time()));
$name = basename($file);
$header = "From: " . $from_name . " <" . $from_mail . ">'r'n";
$header .= "Reply-To: " . $replyto . "'r'n";
$header .= "MIME-Version: 1.0'r'n";
$header .= "Content-Type: multipart/mixed; boundary='"" . $uid . "'"'r'n'r'n";
$header .= "This is a multi-part message in MIME format.'r'n";
$header .= "--" . $uid . "'r'n";
$header .= "Content-type:text/plain; charset=iso-8859-1'r'n";
$header .= "Content-Transfer-Encoding: 7bit'r'n'r'n";
$header .= $message . "'r'n'r'n";
$header .= "--" . $uid . "'r'n";
$header .= "Content-Type: application/octet-stream; name='"" . $filename2 . "'"'r'n"; 
$header .= "Content-Transfer-Encoding: base64'r'n";
$header .= "Content-Disposition: attachment; filename='"" . $filename2 . "'"'r'n'r'n";
$header .= $content . "'r'n'r'n";
$header .= "--" . $uid . "--";
mail($mailto, $subject, "", $header)
?>

就我而言,我使用 laravel(v7) swift mailer 发送邮件。

public function build(): SendMonthlyAbsenceReportToEmployee
{
    $body = "'r'n{$this->prepareFile()}'r'n";
    return $this->view('admin.mail.monthly-absence-report')
        ->with('employee', $this->employee)
        ->attachData($body, 'report.csv', [
            'mime' => 'text/csv'
        ])
        ;
}
private function prepareFile()
{
    $data = $this->service->sendEachEmployeeMonthlyAbsenceReport();
    $header = ['Date', 'Other Info'];
    $df = fopen('php://memory','rw');
    fputcsv($df, ["Name: Sohag", 'Designation: abc', 'Department: new department']);
    fputcsv($df, []);
    fputcsv($df, $header);
    foreach ($data as $row) {
        fputcsv($df, $row);
    }
    rewind($df);
    return stream_get_contents($df);
}