电子邮件 sql 附件问题

Posted

技术标签:

【中文标题】电子邮件 sql 附件问题【英文标题】:email sql attachment issue 【发布时间】:2011-12-05 05:26:10 【问题描述】:

我知道有很多与我类似的问题,是的,我浏览了其中一些,但似乎没有一个回答我的问题。

基本上我已经为客户创建了一个脚本,该脚本创建了他们的数据库转储并将其通过电子邮件发送给他们,我将在下面发布代码,现在数据库信息是通过脚本生成的,并且没有创建物理 sql 文件服务器,而不是将其全部添加到一个变量中,然后使用该变量将数据库信息附加到电子邮件标题。

另外请注意,我以前使用过电子邮件附件的代码,它工作正常,但在那种情况下,文件确实存在,所以我开始认为这是问题所在。

<?php

    //Script configuration section.
    $D_hostname = 'localhost'; # Database hostname.
    $D_username = 'username'; # Database username.
    $D_password = 'password'; # Database password.
    $D_database = 'database'; # Database name.

    $E_from = 'BLOG BACKUP <backup@mywebsite.com>'; # From header.
    $E_subject = '[' . date('d-m-Y') .  ']: This weeks database backup.'; # Email subject.
    $E_content = 'This weeks database backup has been created, please find it attached to this email. Remember to save a copy and retain this email too!<br />'; #Email content.
    $E_filename = date('d-m-Y') .  '_blog_backup.sql'; #Attachment filename.
    $E_filetype = 'application/octet-stream'; # Attachment type.
    $E_recipients = 'email@mywebsite.com, email@myclient.com'; #Email recipients.

    //Connect to the database.
    $connection = mysql_connect($D_hostname, $D_username, $D_password);

    //Select the database
    mysql_select_db($D_database, $connection);

    //Set up an empty array.
    $tables = array();

    //Get a list of all the databases tables.
    $Q_show_tables = mysql_query('SHOW TABLES');

    //Add each table to the array.
    while($R_show_tables = mysql_fetch_row($Q_show_tables))
        $tables[] = $R_show_tables[0];
    

    //Get all rows for each table and create a mySQL query.
    foreach($tables as $table) 

        //Get all rows from the table.
        $Q_get_rows = mysql_query('SELECT * FROM '.$table);
        $C_get_rows = mysql_num_fields($Q_get_rows);

        //Add a drop clause for the table
        $data_row .= 'DROP TABLE ' . $table . ';';

        //Get create table info.
        $Q_create_table = mysql_fetch_row(mysql_query('SHOW CREATE TABLE '.$table));

        //Add the create table clause to the query.
        $data_row.= "\n\n" . $Q_create_table[1] . ";\n\n";

        //Now gather all of the rows.
        for ($int_01 = 0; $int_01 < $C_get_rows; $int_01++) 
            while($R_get_rows = mysql_fetch_row($Q_get_rows)) 

                //Add the insert clause.
                $data_row .= 'INSERT INTO ' . $table . ' VALUES (';

                //For each field write out a row.
                for($int_02 = 0; $int_02 < $C_get_rows; $int_02++) 
                    $R_get_rows[$int_02] = addslashes($R_get_rows[$int_02]);
                    $R_get_rows[$int_02] = ereg_replace("\n","\\n",$R_get_rows[$int_02]);
                    if (isset($R_get_rows[$int_02])) 
                        $data_row .= '"'.$R_get_rows[$int_02].'"' ;
                     else 
                        $data_row .= '""';
                    
                    if ($int_02 < ($num_fields-1))  
                        $data_row .= ','; 
                    
                
            $data_row .= ");\n";
            
        
        $data_row .="\n\n\n";
    

    //Split and encode the data.
    $data_split = chunk_split(base64_encode($data_row));

    //Create a unique boundary
    $new_boundary = md5(time());

    //This is your basic header information such as who the email is from and the date it was sent.
    $mail_header .= 'From: ' . $E_from . "\r\n";
    $mail_header .= 'Date: ' . date('r') . "\r\n";

    //This part of the header first defines to the email client that it is a multipart message and adds the emails content/body.
    $mail_header .= 'Content-Type: multipart/mixed; boundary="' . $new_boundary . '"' . "\r\n\r\n";
    $mail_header .= 'MIME-Version: 1.0' . "\r\n";
    $mail_header .= 'This is a multi-part message in MIME format' . "\r\n";
    $mail_header .= '--' . $new_boundary . "\r\n";
    $mail_header .= 'Content-Type:text/html; charset="iso-8859-1"' . "\r\n";
    $mail_header .= 'Content-Transfer-Encoding: 7bit' . "\r\n\r\n";
    $mail_header .= $E_content . "\r\n\r\n";

    //This part of the header is for the attachment and includes the contents of the file, the files name and other information.
    $mail_header .= '--' . $new_boundary . "\r\n";
    $mail_header .= 'Content-Type: ' . $E_filetype . '; name="' . $E_filename . '"' . "\r\n";
    $mail_header .= 'Content-Transfer-Encoding: base64' . "\r\n";
    $mail_header .= 'Content-Disposition: attachment; filename="' . $E_filename . '"' . "\r\n\r\n";
    $mail_header .= $data_split . "\r\n\r\n";

    //This is needed to stop any rendering errors by email clients and signifies the end of the emails header.
    $mail_header .= '--' . $new_boundary  . '--' . "\r\n";

    //This mails out all of the above.
    mail($E_recipients, $E_subject, '', $mail_header);

?>

问题: 发送邮件时,附件和邮件内容在horde mail客户端或hotmail中根本不显示,但在gmail中可以正常工作。我猜这是邮件标题的问题,但我看不到任何错误。

任何人都可以看到电子邮件标题的任何问题吗?如果是的话,你能告诉我如何解决这个问题吗?

一如既往,非常感谢您的帮助。

【问题讨论】:

我还应该注意,它在 Gmail 中显示正常,但在 Hotmail 或 Horde 中显示不正常。我还没有尝试过任何其他邮件客户端。 作为旁注,电子邮件不是最安全的沟通方式,发送您的数据库对我来说看起来很危险 这不是一个解决方案,但是当我查看您的代码时,我真的不得不建议您查看ezMail,它可以轻松快速地处理通过 PHP 发送邮件的所有问题。无需重新发明***。 【参考方案1】:

天哪!

使用 mime 对象创建格式正确的电子邮件消息并非易事。我已经破解了 metamail 代码,但不会梦想编写自己的 PHP 代码来处理它。如果我没有可以从 PHP(metamail、mutt)调用的支持 mime 的邮件客户端的本机实现,我会使用其中一个免费提供的库来处理它(phpmailer、swiftmailer 是显而易见的候选者)。

我倾向于避免的另一件事是在 PHP 脚本中在内存中创建数据库备份的表示。

我不会做的其他一些事情是:

使用 addlashes 转义 DB 输入 篡改因果关系的本质 避免在需要分离的情况下使用模块化编程 通过电子邮件传输可能非常大的文件(大多数 MTA 会限制电子邮件的大小)

我建议重新开始 - 设置一个 cron 作业以将备份提取到本地文件,然后编写一个 PHP 来控制对该文件的访问 - 并通过电子邮件向用户发送一个链接,让他们可以下载备份。

【讨论】:

是的,我想这将是处理事情的最佳方式,我想我有点喜欢将数据库通过电子邮件发送给客户的想法,我不必担心它们转到我服务器上的数据库存储库,然后在出现问题并且他们没有备份时向我抱怨。尽管这不是我的错,但我宁愿没有对抗和分歧。但是是的,我将编写一个新脚本来处理这一切,而无需通过电子邮件发送数据库。感谢您的回答!【参考方案2】:

你应该把身体放在身体里。它可能是一条 MIME 消息,因此包含标头,但从技术上讲,它仍然是消息的正文,应该是它的位置。

另外,你有一些不必要的\r\n 序列在那里 - 这些不应该破坏了它,但最好不要包含它们。尝试以下代码来构建/发送消息:

//Split and encode the data.
$data_split = chunk_split(base64_encode($data_row));

//Create a unique boundary
$new_boundary = '-------'.md5(time()).'-----';

//This is your basic header information such as who the email is from and the date it was sent.
$mail_header = 'From: ' . $E_from . "\r\n";
$mail_header .= 'Date: ' . date('r') . "\r\n";

//This part of the header first defines to the email client that it is a multipart message and adds the emails content/body.
$mail_header .= 'Content-Type: multipart/mixed; boundary="' . $new_boundary . '"' . "\r\n";
$mail_header .= 'MIME-Version: 1.0' . "\r\n";

// The body (multipart message) starts here:
$mail_body = 'This is a multi-part message in MIME format' . "\r\n";

// HTML content of the email
$mail_body .= "$new_boundary\r\n";
$mail_body .= 'Content-Type: text/html; charset="iso-8859-1"' . "\r\n";
$mail_body .= 'Content-Transfer-Encoding: 7bit' . "\r\n\r\n";
$mail_body .= $E_content . "\r\n";

// This part of the body is for the attachment and includes the contents of the file, the files name and other information.
$mail_body .= "$new_boundary\r\n";
$mail_body .= 'Content-Type: ' . $E_filetype . '; name="' . $E_filename . '"' . "\r\n";
$mail_body .= 'Content-Transfer-Encoding: base64' . "\r\n";
$mail_body .= 'Content-Disposition: attachment; filename="' . $E_filename . '"' . "\r\n\r\n";
$mail_body .= $data_split . "\r\n";

//This is needed to stop any rendering errors by email clients and signifies the end of the email's body.
$mail_body .= "$new_boundary--";

//This mails out all of the above.
mail($E_recipients, $E_subject, $mail_body, $mail_header);

【讨论】:

他正在增加身体。是的,他不知道这段代码是做什么的,但这段代码是在将正文添加到正文中。 @Col.Shrapnel 不正确 - 他的代码将一个空字符串传递给正文,并将整个消息传递给标题。 @DaveRandom 你好戴夫,非常感谢你的回答,不幸的是它不起作用,我很肯定这一切都需要在标题中传递,我之前使用过相同的代码对于电子邮件附件,唯一的区别是在我的其他脚本中,文件实际上存在于服务器上,因为这里没有创建任何文件,信息只是从变量添加到标题中,我认为这就是问题所在。但是我确实尝试了您的代码,它基本上将标题写为电子邮件内容并将我的浏览器冻结了 1-2 分钟哈哈:D

以上是关于电子邮件 sql 附件问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 utl_smtp 包的 PL/SQL 中的多个附件问题

如何用sqlserver自动给用户发邮件 0

如何将SQL查询结果转换为Excel表格推送给企业微信或钉钉的员工账号

PHPMailer拒绝发送没有附件的电子邮件

邮件附件乱码问题

从 Outlook 检索电子邮件附件