使用 PHP Mail() 发送附件?
Posted
技术标签:
【中文标题】使用 PHP Mail() 发送附件?【英文标题】:Send attachments with PHP Mail()? 【发布时间】:2012-08-31 08:22:14 【问题描述】:我需要通过邮件发送 pdf,可以吗?
$to = "xxx";
$subject = "Subject" ;
$message = 'Example message with <b>html</b>';
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
$headers .= 'From: xxx <xxx>' . "\r\n";
mail($to,$subject,$message,$headers);
我错过了什么?
【问题讨论】:
用mail()
功能发送附件比你想象的要难,为了你的时间,尝试使用phpMailer
或者你可以直接链接到它?
@mihai lorga 这不需要服务器端安装吗?如果没有任何扩展或插件也可能,我需要知道如何。
快速谷歌搜索 - webcheatsheet.com/php/send_email_text_html_attachment.php
@ChristianNikkanen 这只是一个设置好的脚本,它还有很多难以完成的功能。为什么要重新发明***?它不使用任何额外的插件。
【参考方案1】:
要发送带附件的电子邮件,我们需要使用 multipart/mixed MIME 类型,指定混合类型将包含在电子邮件中。此外,我们希望使用 multipart/alternative MIME 类型来发送纯文本和 HTML 版本的电子邮件。请看示例:
<?php
//define the receiver of the email
$to = 'youraddress@example.com';
//define the subject of the email
$subject = 'Test email with attachment';
//create a boundary string. It must be unique
//so we use the MD5 algorithm to generate a random hash
$random_hash = md5(date('r', time()));
//define the headers we want passed. Note that they are separated with \r\n
$headers = "From: webmaster@example.com\r\nReply-To: webmaster@example.com";
//add boundary string and mime type specification
$headers .= "\r\nContent-Type: multipart/mixed; boundary=\"PHP-mixed-".$random_hash."\"";
//read the atachment file contents into a string,
//encode it with MIME base64,
//and split it into smaller chunks
$attachment = chunk_split(base64_encode(file_get_contents('attachment.zip')));
//define the body of the message.
ob_start(); //Turn on output buffering
?>
--PHP-mixed-<?php echo $random_hash; ?>
Content-Type: multipart/alternative; boundary="PHP-alt-<?php echo $random_hash; ?>"
--PHP-alt-<?php echo $random_hash; ?>
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Hello World!!!
This is simple text email message.
--PHP-alt-<?php echo $random_hash; ?>
Content-Type: text/html; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
<h2>Hello World!</h2>
<p>This is something with <b>HTML</b> formatting.</p>
--PHP-alt-<?php echo $random_hash; ?>--
--PHP-mixed-<?php echo $random_hash; ?>
Content-Type: application/zip; name="attachment.zip"
Content-Transfer-Encoding: base64
Content-Disposition: attachment
<?php echo $attachment; ?>
--PHP-mixed-<?php echo $random_hash; ?>--
<?php
//copy current buffer contents into $message variable and delete current output buffer
$message = ob_get_clean();
//send the email
$mail_sent = @mail( $to, $subject, $message, $headers );
//if the message is sent successfully print "Mail sent". Otherwise print "Mail failed"
echo $mail_sent ? "Mail sent" : "Mail failed";
?>
如您所见,发送带有附件的电子邮件很容易完成。在前面的示例中,我们有 multipart/mixed MIME 类型,在其中我们有 multipart/alternative MIME 类型,它指定了电子邮件的两个版本。为了在我们的消息中包含附件,我们将指定文件中的数据读入字符串,使用 base64 对其进行编码,将其拆分为更小的块以确保它符合 MIME 规范,然后将其作为附件包含。
取自here。
【讨论】:
复制/粘贴我在 OP cmets 中添加的链接中的内容 良好的 sn-p,尽管我必须在边界字符串之后提供一个额外的换行符才能使其工作。我猜它与php文件的行尾有关。我的编辑器默认使用 LF,但我认为标准也需要回车 (CRLF)。【参考方案2】:我同意 cmets 中的@MihaiIorga - 使用 PHPMailer 脚本。你听起来像是在拒绝它,因为你想要更简单的选择。相信我,与尝试使用 PHP 的内置 mail()
函数自己做相比,PHPMailer 是更容易的选择。 PHP 的mail()
函数确实不是很好。
使用 PHPMailer:
从这里下载 PHPMailer 脚本:http://github.com/PHPMailer/PHPMailer 解压存档并将脚本文件夹复制到项目中方便的位置。 包含主脚本文件 --require_once('path/to/file/class.phpmailer.php');
现在,发送带有附件的电子邮件变得异常简单:
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
$email = new PHPMailer();
$email->SetFrom('you@example.com', 'Your Name'); //Name is optional
$email->Subject = 'Message Subject';
$email->Body = $bodytext;
$email->AddAddress( 'destinationaddress@example.com' );
$file_to_attach = 'PATH_OF_YOUR_FILE_HERE';
$email->AddAttachment( $file_to_attach , 'NameOfFile.pdf' );
return $email->Send();
就这么一行$email->AddAttachment();
——你再简单不过了。
如果您使用 PHP 的 mail()
函数来做这件事,您将编写大量代码,并且您可能会遇到很多非常难以发现的错误。
【讨论】:
我也一样——想使用 mail() 只是因为我的代码中已经有了它。 PHPMAILER 花了我不到 5 分钟的时间来获取发送附件! PHPMAILER 对许多人来说似乎是一个不错的简单方法。但是使用它需要不必要地导入另一个值得信任的东西(即 PHPMailer 中没有错误/等)。为了不盲目相信,需要查看至少 3155 行 sloc (115.456 kb) 的代码。鉴于替代纯 mail() 使用答案,这似乎是一个更糟糕的权衡。替代答案可以使用不到 100 sloc。不喜欢“我想要 A”的答案是“不,使用 B 更好”。其他答案告诉“A 是这样完成的”。 我发现这个问题正在寻找如何使用mail()
函数添加附件的答案。这个答案对我没有帮助。
这不是问题的答案。如何使用 PHPMailer 发送附件不是如何使用 PHP 的 mail() 发送附件,这是所要求的。
这个答案也忽略了项目使用的许可证。通过使用 PHPMailer,您必须确保从源代码中排除该软件包,以防止其 LGPL 许可证出现问题。【参考方案3】:
您可以尝试使用以下代码:
$filename = 'myfile';
$path = 'your path goes here';
$file = $path . "/" . $filename;
$mailto = 'mail@mail.com';
$subject = 'Subject';
$message = 'My message';
$content = file_get_contents($file);
$content = chunk_split(base64_encode($content));
// a random hash will be necessary to send mixed content
$separator = md5(time());
// carriage return type (RFC)
$eol = "\r\n";
// main header (multipart mandatory)
$headers = "From: name <test@test.com>" . $eol;
$headers .= "MIME-Version: 1.0" . $eol;
$headers .= "Content-Type: multipart/mixed; boundary=\"" . $separator . "\"" . $eol;
$headers .= "Content-Transfer-Encoding: 7bit" . $eol;
$headers .= "This is a MIME encoded message." . $eol;
// message
$body = "--" . $separator . $eol;
$body .= "Content-Type: text/plain; charset=\"iso-8859-1\"" . $eol;
$body .= "Content-Transfer-Encoding: 8bit" . $eol;
$body .= $message . $eol;
// attachment
$body .= "--" . $separator . $eol;
$body .= "Content-Type: application/octet-stream; name=\"" . $filename . "\"" . $eol;
$body .= "Content-Transfer-Encoding: base64" . $eol;
$body .= "Content-Disposition: attachment" . $eol;
$body .= $content . $eol;
$body .= "--" . $separator . "--";
//SEND Mail
if (mail($mailto, $subject, $body, $headers))
echo "mail send ... OK"; // or use booleans here
else
echo "mail send ... ERROR!";
print_r( error_get_last() );
2018 年 6 月 14 日编辑
为了提高某些电子邮件提供商的可读性 使用
$body .= $eol . $message . $eol . $eol;
和
$body .= $eol . $content . $eol . $eol;
【讨论】:
$uid 似乎没有使用。 有人在an answer that should be a comment中指出,既然OP的代码是'Example message with <b>html</b>'
,那么Content-Type应该是text/html
而不是text/plain
。我代表他发布评论,因为他没有足够的代表来发布 cmets,我已将答案标记为删除。
在这段代码中,你必须定义$path和$filename吗?它会像 $filename = $_FILES['userfile']['tmp_name']; ?
来自 PHPMailer 的文档... “正确格式化电子邮件非常困难。有无数重叠的 RFC,需要严格遵守极其复杂的格式化和编码规则 - 您可以在网上找到绝大多数代码直接使用 mail() 函数是完全错误的!” ...这是真的!我已经使用类似这个答案的东西来发送带有附件的邮件并且它有效!几天后才发现,虽然 Gmail 显示附件很好,但其他提供商直接在邮件中显示 base64 内容。
正文丢失,只发送附件【参考方案4】:
Swiftmailer 是另一个易于使用的脚本,可自动防御email injection 并使附件变得轻而易举。我也强烈反对使用 PHP 的内置 mail()
函数。
使用方法:
下载Swiftmailer,并将lib
文件夹放入您的项目中
使用require_once 'lib/swift_required.php';
包含主文件
现在在需要邮寄的时候添加代码:
// Create the message
$message = Swift_Message::newInstance()
->setSubject('Your subject')
->setFrom(array('webmaster@mysite.com' => 'Web Master'))
->setTo(array('receiver@example.com'))
->setBody('Here is the message itself')
->attach(Swift_Attachment::fromPath('myPDF.pdf'));
//send the message
$mailer->send($message);
更多信息和选项可以在Swiftmailer Docs找到。
【讨论】:
因为你提供 dwonload 第三方库,我猜 PHPMailer 不是 3rd-party 吗?或者是说@MatthewJohnson 是 swiftmailer 的维护者还是其中的一部分?无论哪种方式,只要解决方案是好的和有效的,投反对票都是不合适的...... @Xsmael,PHPMailer 绝对是第 3 方 :) 我不同意反对意见,因为(至少在当时)该解决方案确实有效。然而,人们可以随心所欲地投票,而且赞成票超过了反对票。【参考方案5】:工作理念:
if (isset($_POST['submit']))
$mailto = $_POST["mailTo"];
$from_mail = $_POST["fromEmail"];
$replyto = $_POST["fromEmail"];
$from_name = $_POST["fromName"];
$message = $_POST["message"];
$subject = $_POST["subject"];
$filename = $_FILES["fileAttach"]["name"];
$content = chunk_split(base64_encode(file_get_contents($_FILES["fileAttach"]["tmp_name"])));
$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";
// You add html "Content-type: text/html; charset=utf-8\n" or for Text "Content-type:text/plain; charset=iso-8859-1\r\n" by I.khan
$header .= "Content-type:text/html; charset=utf-8\n";
$header .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
// User Message you can add HTML if You Selected HTML content
$header .= "<div style='color: red'>" . $message . "</div>\r\n\r\n";
$header .= "--" . $uid . "\r\n";
$header .= "Content-Type: application/octet-stream; name=\"" . $filename . "\"\r\n"; // use different content types here
$header .= "Content-Transfer-Encoding: base64\r\n";
$header .= "Content-Disposition: attachment; filename=\"" . $filename . "\"\r\n\r\n"; // For Attachment
$header .= $content . "\r\n\r\n";
$header .= "--" . $uid . "--";
if (mail($mailto, $subject, "", $header))
echo "<script>alert('Success');</script>"; // or use booleans here
else
echo "<script>alert('Failed');</script>";
【讨论】:
【参考方案6】:针对 PHP 5.5.27 安全更新
$file = $path.$filename;
$content = file_get_contents( $file);
$content = chunk_split(base64_encode($content));
$uid = md5(uniqid(time()));
$file_name = basename($file);
// header
$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";
// message & attachment
$nmessage = "--".$uid."\r\n";
$nmessage .= "Content-type:text/plain; charset=iso-8859-1\r\n";
$nmessage .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
$nmessage .= $message."\r\n\r\n";
$nmessage .= "--".$uid."\r\n";
$nmessage .= "Content-Type: application/octet-stream; name=\"".$filename."\"\r\n";
$nmessage .= "Content-Transfer-Encoding: base64\r\n";
$nmessage .= "Content-Disposition: attachment; filename=\"".$file_name."\"\r\n\r\n";
$nmessage .= $content."\r\n\r\n";
$nmessage .= "--".$uid."--";
if (mail($mailto, $subject, $nmessage, $header))
return true; // Or do something here
else
return false;
【讨论】:
@Jon。 $filename, 是文件的实际名称,$path 是没有文件名的实际文件路径。我认为这些变量的描述性足以声明和建立它们 发送多个附件的注意事项 - 使用$nmessage .= "--".$uid."\r\n";
分隔 MIME 部分,在最后的 MIME 部分之后,使用 $nmessage .= "--".$uid."--";
(如上所示)。
在尝试让愚蠢的 phpmailer 工作感到头疼之后,这终于奏效了。
这个确实有效。接受的答案对我不起作用。它会发送损坏的文件。
这是一个非常清晰和干净的答案。它在 Outlook、Gmail 等接收时有效。整洁的答案。如果你可以用 HTML 消息部分更新,这将变得更加完整。【参考方案7】:
从this page 复制代码 - 在 mail() 中工作
他开始我制作一个稍后可以调用的函数 mail_attachment。他稍后使用附件代码执行此操作。
<?php
function mail_attachment($filename, $path, $mailto, $from_mail, $from_name, $replyto, $subject, $message)
$file = $path.$filename;
$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()));
$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=\"".$filename."\"\r\n"; // use different content types here
$header .= "Content-Transfer-Encoding: base64\r\n";
$header .= "Content-Disposition: attachment; filename=\"".$filename."\"\r\n\r\n";
$header .= $content."\r\n\r\n";
$header .= "--".$uid."--";
if (mail($mailto, $subject, "", $header))
echo "mail send ... OK"; // or use booleans here
else
echo "mail send ... ERROR!";
//start editing and inputting attachment details here
$my_file = "somefile.zip";
$my_path = "/your_path/to_the_attachment/";
$my_name = "Olaf Lederer";
$my_mail = "my@mail.com";
$my_replyto = "my_reply_to@mail.net";
$my_subject = "This is a mail with attachment.";
$my_message = "Hallo,\r\ndo you like this script? I hope it will help.\r\n\r\ngr. Olaf";
mail_attachment($my_file, $my_path, "recipient@mail.org", $my_mail, $my_name, $my_replyto, $my_subject, $my_message);
?>
他的页面上有更多详细信息,并在 cmets 部分回答了一些问题。
【讨论】:
【参考方案8】:在处理格式错误的附件一段时间后,这是我使用的代码:
$email = new PHPMailer();
$email->From = 'from@somedomain.com';
$email->FromName = 'FromName';
$email->Subject = 'Subject';
$email->Body = 'Body';
$email->AddAddress( 'to@somedomain.com' );
$email->AddAttachment( "/path/to/filename.ext" , "filename.ext", 'base64', 'application/octet-stream' );
$email->Send();
【讨论】:
【参考方案9】:100% 工作概念在 php 中发送带有附件的电子邮件:
if (isset($_POST['submit']))
extract($_POST);
require_once('mail/class.phpmailer.php');
$subject = "$name Applied For - $position";
$email_message = "<div>Thanks for Applying ....</div> ";
$mail = new PHPMailer;
$mail->IsSMTP(); // telling the class to use SMTP
$mail->Host = "mail.companyname.com"; // SMTP server
$mail->SMTPDebug = 0;
$mail->SMTPAuth = true;
$mail->SMTPSecure = "ssl";
$mail->Host = "smtp.gmail.com";
$mail->Port = 465;
$mail->IsHTML(true);
$mail->Username = "info@companyname.com"; // GMAIL username
$mail->Password = "mailPassword"; // GMAIL password
$mail->SetFrom('info@companyname.com', 'new application submitted');
$mail->AddReplyTo("name@yourdomain.com","First Last");
$mail->Subject = "your subject";
$mail->AltBody = "To view the message, please use an HTML compatible email viewer!"; // optional, comment out and test
$mail->MsgHTML($email_message);
$address = 'info@companyname.com';
$mail->AddAddress($address, "companyname");
$mail->AddAttachment($_FILES['file']['tmp_name'], $_FILES['file']['name']); // attachment
if (!$mail->Send())
/* Error */
echo 'Message not Sent! Email at info@companyname.com';
else
/* Success */
echo 'Sent Successfully! <b> Check your Mail</b>';
我将此代码用于带有附件的 google smtp 邮件发送......
注意:从这里下载 PHPMailer 库 -> https://github.com/PHPMailer/PHPMailer
【讨论】:
【参考方案10】:我最终编写了自己的电子邮件发送/编码功能。这对我发送 PDF 附件很有效。我没有在生产中使用过其他功能。
注意:尽管规范非常强调必须使用 \r\n 来分隔标题,但我发现它仅在我使用 PHP_EOL 时才有效。我只在 Linux 上测试过这个。 YMMV
<?php
# $args must be an associative array
# required keys: from, to, body
# body can be a string or a [tree of] associative arrays. See examples below
# optional keys: subject, reply_to, cc, bcc
# EXAMPLES:
# # text-only email:
# email2(array(
# 'from' => 'noreply@foo.com',
# 'to' => 'jason@jasonwoof.com',
# 'subject' => 'test',
# # body will be text/plain because we're passing a string that doesn't start with '<'
# 'body' => 'Hi, testing 1 2 3',
# ));
#
# # html-only email
# email2(array(
# 'from' => 'noreply@foo.com',
# 'to' => 'jason@jasonwoof.com',
# 'subject' => 'test',
# # body will be text/html because we're passing a string that starts with '<'
# 'body' => '<h1>Hi!</h1>I like <a href="http://cheese.com">cheese</a>',
# ));
#
# # text-only email (explicitly, in case first character is dynamic or something)
# email2(array(
# 'from' => 'noreply@foo.com',
# 'to' => 'jason@jasonwoof.com',
# 'subject' => 'test',
# # body will be text/plain because we're passing a string that doesn't start with '<'
# 'body' => array(
# 'type' => 'text',
# 'body' => $message_text,
# )
# ));
#
# # email with text and html alternatives (auto-detected mime types)
# email2(array(
# 'from' => 'noreply@foo.com',
# 'to' => 'jason@jasonwoof.com',
# 'subject' => 'test',
# 'body' => array(
# 'type' => 'alternatives',
# 'body' => array(
# "Hi!\n\nI like cheese",
# '<h1>Hi!</h1><p>I like <a href="http://cheese.com">cheese</a></p>',
# )
# )
# ));
#
# # email with text and html alternatives (explicit types)
# email2(array(
# 'from' => 'noreply@foo.com',
# 'to' => 'jason@jasonwoof.com',
# 'subject' => 'test',
# 'body' => array(
# 'type' => 'alternatives',
# 'body' => array(
# array(
# 'type' => 'text',
# 'body' => "Hi!\n\nI like cheese",
# ),
# array(
# 'type' => 'html',
# 'body' => '<h1>Hi!</h1><p>I like cheese</p>',
# ),
# )
# )
# ));
#
# # email with an attachment
# email2(array(
# 'from' => 'noreply@foo.com',
# 'to' => 'jason@jasonwoof.com',
# 'subject' => 'test',
# 'body' => array(
# 'type' => 'mixed',
# 'body' => array(
# "Hi!\n\nCheck out this (inline) image",
# array(
# 'type' => 'image/png',
# 'disposition' => 'inline',
# 'body' => $image_data, # raw file contents
# ),
# "Hi!\n\nAnd here's an attachment",
# array(
# 'type' => 'application/pdf; name="attachment.pdf"',
# 'disposition' => 'attachment; filename="attachment.pdf"',
# 'body' => $pdf_data, # raw file contents
# ),
# "Or you can use shorthand:",
# array(
# 'type' => 'application/pdf',
# 'attachment' => 'attachment.pdf', # name for client (not data source)
# 'body' => $pdf_data, # raw file contents
# ),
# )
# )
# ))
function email2($args)
if (!isset($args['from'])) return 1;
$from = $args['from'];
if (!isset($args['to'])) return 2;
$to = $args['to'];
$subject = isset($args['subject']) ? $args['subject'] : '';
$reply_to = isset($args['reply_to']) ? $args['reply_to'] : '';
$cc = isset($args['cc']) ? $args['cc'] : '';
$bcc = isset($args['bcc']) ? $args['bcc'] : '';
#FIXME should allow many more characters here (and do Q encoding)
$subject = isset($args['subject']) ? $args['subject'] : '';
$subject = preg_replace("|[^a-z0-9 _/#'.:&,-]|i", '_', $subject);
$headers = "From: $from";
if($reply_to)
$headers .= PHP_EOL . "Reply-To: $reply_to";
if($cc)
$headers .= PHP_EOL . "CC: $cc";
if($bcc)
$headers .= PHP_EOL . "BCC: $bcc";
$r = email2_helper($args['body']);
$headers .= PHP_EOL . $r[0];
$body = $r[1];
if (mail($to, $subject, $body, $headers))
return 0;
else
return 5;
function email2_helper($body, $top = true)
if (is_string($body))
if (substr($body, 0, 1) == '<')
return email2_helper(array('type' => 'html', 'body' => $body), $top);
else
return email2_helper(array('type' => 'text', 'body' => $body), $top);
# now we can assume $body is an associative array
# defaults:
$type = 'application/octet-stream';
$mime = false;
$boundary = null;
$disposition = null;
$charset = false;
# process 'type' first, because it sets defaults for others
if (isset($body['type']))
$type = $body['type'];
if ($type === 'text')
$type = 'text/plain';
$charset = true;
elseif ($type === 'html')
$type = 'text/html';
$charset = true;
elseif ($type === 'alternative' || $type === 'alternatives')
$mime = true;
$type = 'multipart/alternative';
elseif ($type === 'mixed')
$mime = true;
$type = 'multipart/mixed';
if (isset($body['disposition']))
$disposition = $body['disposition'];
if (isset($body['attachment']))
if ($disposition == null)
$disposition = 'attachment';
$disposition .= "; filename=\"$body['attachment']\"";
$type .= "; name=\"$body['attachment']\"";
# make headers
$headers = array();
if ($top && $mime)
$headers[] = 'MIME-Version: 1.0';
if ($mime)
$boundary = md5('5sd^%Ca)~aAfF0=4mIN' . rand() . rand());
$type .= "; boundary=$boundary";
if ($charset)
$type .= '; charset=' . (isset($body['charset']) ? $body['charset'] : 'UTF-8');
$headers[] = "Content-Type: $type";
if ($disposition !== null)
$headers[] = "Content-Disposition: $disposition";
$data = '';
# return array, first el is headers, 2nd is body (php's mail() needs them separate)
if ($mime)
foreach ($body['body'] as $sub_body)
$data .= "--$boundary" . PHP_EOL;
$r = email2_helper($sub_body, false);
$data .= $r[0] . PHP_EOL . PHP_EOL; # headers
$data .= $r[1] . PHP_EOL . PHP_EOL; # body
$data .= "--$boundary--";
else
if(preg_match('/[^\x09\x0A\x0D\x20-\x7E]/', $body['body']))
$headers[] = "Content-Transfer-Encoding: base64";
$data .= chunk_split(base64_encode($body['body']));
else
$data .= $body['body'];
return array(join(PHP_EOL, $headers), $data);
【讨论】:
我刚刚意识到我的代码调用了一些我没有包含的函数。他们只是确保 to/from/cc/etc 值是合法的。我删除了它们,现在这段代码可以自己工作了。【参考方案11】:这对我有用。它还附加了多个附件。轻松
<?php
if ($_POST && isset($_FILES['file']))
$recipient_email = "recipient@yourmail.com"; //recepient
$from_email = "info@your_domain.com"; //from email using site domain.
$subject = "Attachment email from your website!"; //email subject line
$sender_name = filter_var($_POST["s_name"], FILTER_SANITIZE_STRING); //capture sender name
$sender_email = filter_var($_POST["s_email"], FILTER_SANITIZE_STRING); //capture sender email
$sender_message = filter_var($_POST["s_message"], FILTER_SANITIZE_STRING); //capture message
$attachments = $_FILES['file'];
//php validation
if (strlen($sender_name) < 4)
die('Name is too short or empty');
if (!filter_var($sender_email, FILTER_VALIDATE_EMAIL))
die('Invalid email');
if (strlen($sender_message) < 4)
die('Too short message! Please enter something');
$file_count = count($attachments['name']); //count total files attached
$boundary = md5("specialToken$4332"); // boundary token to be used
if ($file_count > 0) //if attachment exists
//header
$headers = "MIME-Version: 1.0\r\n";
$headers .= "From:" . $from_email . "\r\n";
$headers .= "Reply-To: " . $sender_email . "" . "\r\n";
$headers .= "Content-Type: multipart/mixed; boundary = $boundary\r\n\r\n";
//message text
$body = "--$boundary\r\n";
$body .= "Content-Type: text/plain; charset=ISO-8859-1\r\n";
$body .= "Content-Transfer-Encoding: base64\r\n\r\n";
$body .= chunk_split(base64_encode($sender_message));
//attachments
for ($x = 0; $x < $file_count; $x++)
if (!empty($attachments['name'][$x]))
if ($attachments['error'][$x] > 0) //exit script and output error if we encounter any
$mymsg = array(
1 => "The uploaded file exceeds the upload_max_filesize directive in php.ini",
2 => "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form",
3 => "The uploaded file was only partially uploaded",
4 => "No file was uploaded",
6 => "Missing a temporary folder");
die($mymsg[$attachments['error'][$x]]);
//get file info
$file_name = $attachments['name'][$x];
$file_size = $attachments['size'][$x];
$file_type = $attachments['type'][$x];
//read file
$handle = fopen($attachments['tmp_name'][$x], "r");
$content = fread($handle, $file_size);
fclose($handle);
$encoded_content = chunk_split(base64_encode($content)); //split into smaller chunks (RFC 2045)
$body .= "--$boundary\r\n";
$body .= "Content-Type: $file_type; name=" . $file_name . "\r\n";
$body .= "Content-Disposition: attachment; filename=" . $file_name . "\r\n";
$body .= "Content-Transfer-Encoding: base64\r\n";
$body .= "X-Attachment-Id: " . rand(1000, 99999) . "\r\n\r\n";
$body .= $encoded_content;
else //send plain email otherwise
$headers = "From:" . $from_email . "\r\n" .
"Reply-To: " . $sender_email . "\n" .
"X-Mailer: PHP/" . phpversion();
$body = $sender_message;
$sentMail = @mail($recipient_email, $subject, $body, $headers);
if ($sentMail) //output success or failure messages
die('Thank you for your email');
else
die('Could not send mail! Please check your PHP mail configuration.');
?>
【讨论】:
由于用户输入缺乏验证和适当的上下文转义,此代码容易受到标头注入攻击。 @Synchro ..这是我为多个附件找到的唯一对我有用的代码..您能否建议如何以安全的方式使用它。【参考方案12】: $to = "to@gmail.com";
$subject = "Subject Of The Mail";
$message = "Hi there,<br/><br/>This is my message.<br><br>";
$headers = "From: From-Name<from@gmail.com>";
// boundary
$semi_rand = md5(time());
$mime_boundary = "==Multipart_Boundary_x$semi_randx";
// headers for attachment
$headers .= "\nMIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" . " boundary=\"$mime_boundary\"";
// multipart boundary
$message = "This is a multi-part message in MIME format.\n\n" . "--$mime_boundary\n" . "Content-Type: text/html; charset=ISO-8859-1\"\n" . "Content-Transfer-Encoding: 7bit\n\n" . $message . "\n\n";
$message .= "--$mime_boundary\n";
$filepath = 'uploads/'.$_FILES['image']['name'];
move_uploaded_file($_FILES['image']['tmp_name'], $filepath); //upload the file
$filename = $_FILES['image']['name'];
$file = fopen($filepath, "rb");
$data = fread($file, filesize($filepath));
fclose($file);
$data = chunk_split(base64_encode($data));
$message .= "Content-Type: \"application/octet-stream\";\n" . " name=\"$filename\"\n" .
"Content-Disposition: attachment;\n" . " filename=\"$filename\"\n" .
"Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
$message .= "--$mime_boundary\n";
mail($to, $subject, $message, $headers);
【讨论】:
【参考方案13】:由于指定的附件格式 (application/octet-stream
),以上答案均不适合我。使用 application/pdf
以获得 PDF 文件的最佳效果。
<?php
// just edit these
$to = "email1@domain.com, email2@domain.com"; // addresses to email pdf to
$from = "sent_from@domain.com"; // address message is sent from
$subject = "Your PDF email subject"; // email subject
$body = "<p>The PDF is attached.</p>"; // email body
$pdfLocation = "./your-pdf.pdf"; // file location
$pdfName = "pdf-file.pdf"; // pdf file name recipient will get
$filetype = "application/pdf"; // type
// creates headers and mime boundary
$eol = PHP_EOL;
$semi_rand = md5(time());
$mime_boundary = "==Multipart_Boundary_$semi_rand";
$headers = "From: $from$eolMIME-Version: 1.0$eol" .
"Content-Type: multipart/mixed;$eol boundary=\"$mime_boundary\"";
// add html message body
$message = "--$mime_boundary$eol" .
"Content-Type: text/html; charset=\"iso-8859-1\"$eol" .
"Content-Transfer-Encoding: 7bit$eol$eol$body$eol";
// fetches pdf
$file = fopen($pdfLocation, 'rb');
$data = fread($file, filesize($pdfLocation));
fclose($file);
$pdf = chunk_split(base64_encode($data));
// attaches pdf to email
$message .= "--$mime_boundary$eol" .
"Content-Type: $filetype;$eol name=\"$pdfName\"$eol" .
"Content-Disposition: attachment;$eol filename=\"$pdfName\"$eol" .
"Content-Transfer-Encoding: base64$eol$eol$pdf$eol--$mime_boundary--";
// Sends the email
if(mail($to, $subject, $message, $headers))
echo "The email was sent.";
else
echo "There was an error sending the mail.";
【讨论】:
$headers = "From: $from$eolMIME-Version: 1.0$eol" 在 $eolMIME 上不断抛出未定义变量错误。 嗯...替换"From: $from$eolMIME-Version: 1.0$eol"
为 "From: $from" . "$eolMIME-Version: 1.0$eol"
也许它不会让你像在某些版本的 php 中那样添加两个变量,它适用于我正在使用的那个。对于那个很抱歉。事实上,您可能想用" . "$eol
替换所有$eol
实例,这样一来就完成了。【参考方案14】:
HTML 代码:
<form enctype="multipart/form-data" method="POST" action="">
<label>Your Name <input type="text" name="sender_name" /> </label>
<label>Your Email <input type="email" name="sender_email" /> </label>
<label>Your Contact Number <input type="tel" name="contactnumber" /> </label>
<label>Subject <input type="text" name="subject" /> </label>
<label>Message <textarea name="description"></textarea> </label>
<label>Attachment <input type="file" name="attachment" /></label>
<label><input type="submit" name="button" value="Submit" /></label>
</form>
PHP 代码:
<?php
if($_POST['button'])
//Server Variables
$server_name = "Your Name";
$server_mail = "your_mail@domain.com";
//Name Attributes of HTML FORM
$sender_email = "sender_email";
$sender_name = "sender_name";
$contact = "contactnumber";
$mail_subject = "subject";
$input_file = "attachment";
$message = "description";
//Fetching HTML Values
$sender_name = $_POST[$sender_name];
$sender_mail = $_POST[$sender_email];
$message = $_POST[$message];
$contact= $_POST[$contact];
$mail_subject = $_POST[$mail_subject];
//Checking if File is uploaded
if(isset($_FILES[$input_file]))
//Main Content
$main_subject = "Subject seen on server's mail";
$main_body = "Hello $server_name,<br><br>
$sender_name ,contacted you through your website and the details are as below: <br><br>
Name : $sender_name <br>
Contact Number : $contact <br>
Email : $sender_mail <br>
Subject : $mail_subject <br>
Message : $message.";
//Reply Content
$reply_subject = "Subject seen on sender's mail";
$reply_body = "Hello $sender_name,<br>
\t Thank you for filling the contact form. We will revert back to you shortly.<br><br>
This is an auto generated mail sent from our Mail Server.<br>
Please do not reply to this mail.<br>
Regards<br>
$server_name";
//#############################DO NOT CHANGE ANYTHING BELOW THIS LINE#############################
$filename= $_FILES[$input_file]['name'];
$file = chunk_split(base64_encode(file_get_contents($_FILES[$input_file]['tmp_name'])));
$uid = md5(uniqid(time()));
//Sending mail to Server
$retval = mail($server_mail, $main_subject, "--$uid\r\nContent-type:text/html; charset=iso-8859-1\r\nContent-Transfer-Encoding: 7bit\r\n\r\n $main_body \r\n\r\n--$uid\r\nContent-Type: application/octet-stream; name=\"$filename\"\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment; filename=\"$filename\"\r\n\r\n$file\r\n\r\n--$uid--", "From: $sender_name <$sender_mail>\r\nReply-To: $sender_mail\r\nMIME-Version: 1.0\r\nContent-Type: multipart/mixed; boundary=\"$uid\"\r\n\r\n");
//Sending mail to Sender
$retval = mail($sender_mail, $reply_subject, $reply_body , "From: $server_name<$server_mail>\r\nMIME-Version: 1.0\r\nContent-type: text/html\r\n");
//#############################DO NOT CHANGE ANYTHING ABOVE THIS LINE#############################
//Output
if ($retval == true)
echo "Message sent successfully...";
echo "<script>window.location.replace('index.html');</script>";
else
echo "Error<br>";
echo "Message could not be sent...Try again later";
echo "<script>window.location.replace('index.html');</script>";
else
echo "Error<br>";
echo "File Not Found";
else
echo "Error<br>";
echo "Unauthorised Access";
【讨论】:
【参考方案15】:您可以使用我创建的此类发送常规或附件电子邮件。
这里是如何使用它的示例链接。
https://github.com/Nerdtrix/EZMAIL
【讨论】:
【参考方案16】:ContactRequestSubmitted姓名:'.$name.'
电子邮件:'.$email.'
主题:'.$subject.'
消息:'.$message.'
';$headers= "From:$fromName"."";if(!empty($uploadedFile)&&file_exists($uploadedFile))$semi_rand=md5(time());$mime_boundary="==Multipart_Boundary_x$semi_randx";$ headers.="\nMIME-Version:1.0\n"."Content-Type:multipart/mixed;\n"."boundary=\"$mime_boundary\"";$message="--$mime_boundary \n"."Content-Type:text/html;charset=\"UTF-8\"\n"."Content-Transfer-Encoding:7bit\n\n".$htmlContent."\n\n"; if(is_file($uploadedFile))$message.="--$mime_boundary\n";$fp=@fopen($uploadedFile,"rb");$data=@fread($fp,filesize($ uploadFile));@fclose($fp);$data=chunk_split(base64_encode($data));$message.="Content-Type:application/octet-stream;name=\"".basename($uploadedFile)。 "\"\n"."Content-Description:".basename($uploadedFile)."\n"."Content-Disposition:attachment;\n"."filename=\"".basename($uploadedFile)." \";size=".filesize($uploadedFile).";\n"."正文nt-Transfer-Encoding:base64\n\n".$data."\n\n";$message.="--$mime_boundary--";$returnpath="-f".$email; $mail=mail($toEmail,$emailSubject,$message,$headers,$returnpath);@unlink($uploadedFile);else$headers.="\r\n"."MIME-Version:1.0"; $headers.="\r\n"."Content-type:text/html;charset=UTF-8";$mail=mail($toEmail,$emailSubject,$htmlContent,$headers);if($mail )$statusMsg='Yourcontactrequesthasbeensubmittedsuccessfully!';$msgClass='succdiv';$postData='';else$statusMsg='Yourcontactrequestsubmission failed,pleasetry again.';else$statusMsg='请填写所有字段。'; ?>">"placeholder="Name"required="">"placeholder="Emailaddress"required="">"placeholder="Subject"required="">[来源][1]
https://www.findinall.com/blog/how-to-test-mail-and-send-attachment-in-mail/
【讨论】:
以上是关于使用 PHP Mail() 发送附件?的主要内容,如果未能解决你的问题,请参考以下文章
基于PHP自带的mail函数实现发送邮件以及带有附件的邮件功能
PHP 的 mail() 函数附件支持在 Windows 上是不是有点损坏?