我正在尝试使用亚马逊SES API发送包含附件(pdf文件)的电子邮件。
我正在使用Symfony2,所以我在项目中包含了AmazonWebServiceBundle。 我可以使用以下代码轻松发送一封简单的电子邮件(没有附件):
$ses = $this->container->get('aws_ses');
$recip = array("ToAddresses"=>array("Quilly@yourownpoet.com"));
$message = array("Subject.Data"=>"My Subject","Body.Text.Data"=>"My Mail body");
$result = $ses->send_email("Quilly@yourownpoet.com",$recip, $message);
不幸的是,要发送带附件的电子邮件,我需要使用sendRawEmail函数而不是send_email函数。
我无法找到如何使用此功能,有人可以帮忙吗?
答案 0 :(得分:3)
是的,使用SES发送带附件的电子邮件很痛苦。也许这会帮助那些仍在努力解决的人。我编写了一个简单的类,有助于简化对sendRawEmail的调用。
用法:
$subject_str = "Some Subject";
$body_str = "<strong>Some email body</strong>";
$attachment_str = file_get_contents("/htdocs/test/sample.pdf");
//send the email
$result = SESUtils::deliver_mail_with_attachment(
array('email1@gmail.com', 'email2@lutz-engr.com'),
$subject_str, $body_str, 'sender@verifiedbyaws',
$attachment_str);
//now handle the $result if you wish
类别:
<?php
require 'AWSSDKforPHP/aws.phar';
use Aws\Ses\SesClient;
/**
* SESUtils is a tool to make it easier to work with Amazon Simple Email Service
* Features:
* A client to prepare emails for use with sending attachments or not
*
* There is no warranty - use this code at your own risk.
* @author sbossen
* http://right-handed-monkey.blogspot.com
*/
class SESUtils {
const version = "1.0";
const AWS_KEY = "your_aws_key";
const AWS_SEC = "your_aws_secret";
const AWS_REGION = "us-east-1";
const BOUNCER = "bouncer@yourdomain.com"; //if used, this also needs to be a verified email
const LINEBR = "\n";
const MAX_ATTACHMENT_NAME_LEN = 60;
/**
* Usage
* $result = SESUtils::deliver_mail_with_attachment(array('receipt@r.com', 'receipt2@b.com'), $subject_str, $body_str, 'validatedsender@aws', $attachment_str);
* use $result->success to check if it was successful
* use $result->message_id to check later with Amazon for further processing
* use $result->result_text to look for error text if the task was not successful
*
* @param type $to - individual address or array of email addresses
* @param type $subject - UTF-8 text for the subject line
* @param type $body - Text for the email
* @param type $from - email address of the sender (Note: must be validated with AWS as a sender)
* @return \ResultHelper
*/
public static function deliver_mail_with_attachment($to, $subject, $body, $from, &$attachment = "", $attachment_name = "doc.pdf", $attachment_type = "Application/pdf", $is_file = false, $encoding = "base64", $file_arr = null) {
$result = new ResultHelper();
//get the client ready
$client = SesClient::factory(array(
'key' => self::AWS_KEY,
'secret' => self::AWS_SEC,
'region' => self::AWS_REGION
));
//build the message
if (is_array($to)) {
$to_str = rtrim(implode(',', $to), ',');
} else {
$to_str = $to;
}
$msg = "To: $to_str".self::LINEBR;
$msg .="From: $from".self::LINEBR;
//in case you have funny characters in the subject
$subject = mb_encode_mimeheader($subject, 'UTF-8');
$msg .="Subject: $subject".self::LINEBR;
$msg .="MIME-Version: 1.0".self::LINEBR;
$msg .="Content-Type: multipart/alternative;".self::LINEBR;
$boundary = uniqid("_Part_".time(), true); //random unique string
$msg .=" boundary=\"$boundary\"".self::LINEBR;
$msg .=self::LINEBR;
//now the actual message
$msg .="--$boundary".self::LINEBR;
//first, the plain text
$msg .="Content-Type: text/plain; charset=utf-8".self::LINEBR;
$msg .="Content-Transfer-Encoding: 7bit".self::LINEBR;
$msg .=self::LINEBR;
$msg .=strip_tags($body);
$msg .=self::LINEBR;
//now, the html text
$msg .="--$boundary".self::LINEBR;
$msg .="Content-Type: text/html; charset=utf-8".self::LINEBR;
$msg .="Content-Transfer-Encoding: 7bit".self::LINEBR;
$msg .=self::LINEBR;
$msg .=$body;
$msg .=self::LINEBR;
//add attachments
if (!empty($attachment)) {
$msg .="--$boundary".self::LINEBR;
$msg .="Content-Transfer-Encoding: base64".self::LINEBR;
$clean_filename = mb_substr($attachment_name, 0, self::MAX_ATTACHMENT_NAME_LEN);
$msg .="Content-Type: $attachment_type; name=$clean_filename;".self::LINEBR;
$msg .="Content-Disposition: attachment; filename=$clean_filename;".self::LINEBR;
$msg .=self::LINEBR;
$msg .=base64_encode($attachment);
//only put this mark on the last entry
if (!empty($file_arr))
$msg .="==".self::LINEBR;
$msg .="--$boundary";
}
if (!empty($file_arr) && is_array($file_arr)) {
foreach ($file_arr as $file) {
$msg .="Content-Transfer-Encoding: base64".self::LINEBR;
$clean_filename = mb_substr($attachment_name, 0, self::MAX_ATTACHMENT_NAME_LEN);
$msg .="Content-Type: application/octet-stream; name=$clean_filename;".self::LINEBR;
$msg .="Content-Disposition: attachment; filename=$clean_filename;".self::LINEBR;
$msg .=self::LINEBR;
$msg .=base64_encode($attachment);
//only put this mark on the last entry
if (!empty($file_arr))
$msg .="==".self::LINEBR;
$msg .="--$boundary";
}
}
//close email
$msg .="--".self::LINEBR;
//now send the email out
try {
$ses_result = $client->sendRawEmail(array(
'RawMessage' => array('Data' => base64_encode($msg))), array('Source' => $from, 'Destinations' => $to_str));
if ($ses_result) {
$result->message_id = $ses_result->get('MessageId');
} else {
$result->success = false;
$result->result_text = "Amazon SES did not return a MessageId";
}
} catch (Exception $e) {
$result->success = false;
$result->result_text = $e->getMessage()." - To: $to_str, Sender: $from, Subject: $subject";
}
return $result;
}
}
class ResultHelper {
public $success = true;
public $result_text = "";
public $message_id = "";
}
?>
我写了一篇博文来解决这个问题,也许对您或其他人有用:http://righthandedmonkey.com/2013/06/how-to-use-amazon-ses-to-send-email-php.html
答案 1 :(得分:1)
我设法使用Amazon SES sendRawEmail以下面的方式创建一个原始MIME消息,以发送带附件(.pdf文件)的电子邮件。这是用于普通的javascript用法;一个人可以肯定地进一步改进它还添加其他内容类型。
使用像jsPDF&amp; amp; html2Canvas创建PDF文件&amp;将内容保存到变量&amp;得到基数为64的数据:
var pdfOutput = pdf.output();
var myBase64Data = btoa(pdfOutput);
使用以下代码创建MIME消息。请注意,序列很重要,否则电子邮件将最终显示为公开所有base 64数据的文本电子邮件:
var fileName = "Attachment.pdf";
var rawMailBody = "From: testmail@gmail.com\nTo: testmail@gmail.com\n";
rawMailBody = rawMailBody + "Subject: Test Subject\n";
rawMailBody = rawMailBody + "MIME-Version: 1.0\n";
rawMailBody = rawMailBody + "Content-Type: multipart/mixed; boundary=\"NextPart\"\n\n";
rawMailBody = rawMailBody + "--NextPart\n";
rawMailBody = rawMailBody + "Content-Type: application/octet-stream\n";
rawMailBody = rawMailBody + "Content-Transfer-Encoding: base64\n";
rawMailBody = rawMailBody + "Content-Disposition: attachment; filename=\"" + fileName + "\"\n\n";
rawMailBody = rawMailBody + "Content-ID random2384928347923784letters\n";
rawMailBody = rawMailBody + myBase64Data+"\n\n";
rawMailBody = rawMailBody + "--NextPart\n";
调用sendRawEmail:
var params = {
RawMessage: {
Data: rawMailBody
},
Destinations: [],
Source: 'testmail@gmail.com'
};
ses.sendRawEmail(params, function(err, data) {
if (err) alert("Error: "+err); // an error occurred
else {
alert("Success: "+data); // successful response
}
});
答案 2 :(得分:1)
手工构建电子邮件,正如您明确表达的那样,“太痛苦了”,维护自己的服务器以发送电子邮件也是如此。这就是为什么我建议使用库来创建电子邮件的原因。
例如,Swift mailer有一个名为Swift_Message的类,可用于创建电子邮件和include attachments。
以下示例直接取自documentation:
$message = (new Swift_Message())
->setSubject('Your subject')
->setFrom(['john@doe.com' => 'John Doe'])
->setTo(['receiver@domain.org', 'other@domain.org' => 'A name'])
->setBody('Here is the message itself')
->addPart('<q>Here is the message itself</q>', 'text/html')
->attach(Swift_Attachment::fromPath('my-document.pdf'))
然后只需调用消息的toString
方法并将其设置为RawMessage
$result = $client->sendRawEmail([
'RawMessage' => [
'Data' => $message.toString()
]
]);
或者,您可以设置symfony + swift mailer以使用SES SMTP端点,有关详细信息,请参见symfony documentation。
答案 3 :(得分:0)
经过多次尝试,我得出结论,直接从代码发送电子邮件给Amazon SES太麻烦了。
所以我没有更改代码中的内容并改为配置我的后缀服务器。
我遵循了这个程序:http://docs.amazonwebservices.com/ses/latest/DeveloperGuide/SMTP.MTAs.Postfix.html并使用STARTTLS配置了集成。
我不得不在亚马逊控制台中要求提供SMTP凭据。
现在它运行正常,通过Amazon SES正确发送电子邮件。