简体   繁体   English

如何使用 AWS SES 在电子邮件中发送附件

[英]how to send attachments in emails using AWS SES

I'm trying to send an email programmatically using amazon's SES library using the code from here .我正在尝试使用此处的代码使用亚马逊的 SES 库以编程方式发送电子邮件。 After tweaking I have the following pieces of code.调整后,我有以下代码段。

SESUtils.php SESUtils.php

<?php

require_once('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
 *
 * Update: Error checking and new params input array provided by Michael Deal
 */
class SESUtils {

const version = "1.0";
const AWS_KEY = SES_KEY;
const AWS_SEC = SES_SECRET;
const AWS_REGION = "us-east-1";
const MAX_ATTACHMENT_NAME_LEN = 60;

/**
 * Usage:
    $params = array(
      "to" => "email1@gmail.com",
      "subject" => "Some subject",
      "message" => "<strong>Some email body</strong>",
      "from" => "sender@verifiedbyaws",
      //OPTIONAL
      "replyTo" => "reply_to@gmail.com",
      //OPTIONAL
      "files" => array(
        1 => array(
           "name" => "filename1", 
          "filepath" => "/path/to/file1.txt", 
          "mime" => "application/octet-stream"
        ),
        2 => array(
           "name" => "filename2", 
          "filepath" => "/path/to/file2.txt", 
          "mime" => "application/octet-stream"
        ),
      )
    );

  $res = SESUtils::sendMail($params);

 * NOTE: When sending a single file, omit the key (ie. the '1 =>') 
 * or use 0 => array(...) - otherwise the file will come out garbled
 * 
 * use $res->success to check if it was successful
 * use $res->message_id to check later with Amazon for further processing
 * use $res->result_text to look for error text if the task was not successful
 * 
 * @param array $params - array of parameters for the email
 * @return \ResultHelper
 */
public static function sendMail($params) {

    $to = self::getParam($params, 'to', true);
    $subject = self::getParam($params, 'subject', true);
    $body = self::getParam($params, 'message', true);
    $from = self::getParam($params, 'from', true);
    $replyTo = self::getParam($params, 'replyTo');
    $files = self::getParam($params, 'files');

    $res = 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\n";
    $msg .= "From: $from\n";

    if ($replyTo) {
        $msg .= "Reply-To: $replyTo\n";
    }

    // in case you have funny characters in the subject
    $subject = mb_encode_mimeheader($subject, 'UTF-8');
    $msg .= "Subject: $subject\n";
    $msg .= "MIME-Version: 1.0\n";
    $msg .= "Content-Type: multipart/alternative;\n";
    $boundary = uniqid("_Part_".time(), true); //random unique string
    $msg .= " boundary=\"$boundary\"\n";
    $msg .= "\n";

    // now the actual message
    $msg .= "--$boundary\n";

    // first, the plain text
    $msg .= "Content-Type: text/plain; charset=utf-8\n";
    $msg .= "Content-Transfer-Encoding: 7bit\n";
    $msg .= "\n";
    $msg .= strip_tags($body);
    $msg .= "\n";

    // now, the html text
    $msg .= "--$boundary\n";
    $msg .= "Content-Type: text/html; charset=utf-8\n";
    $msg .= "Content-Transfer-Encoding: 7bit\n";
    $msg .= "\n";
    $msg .= $body;
    $msg .= "\n";

    // add attachments
    if (is_array($files)) {
        $count = count($files);
        foreach ($files as $idx => $file) {
            if ($idx !== 0)
                $msg .= "\n";
            $msg .= "--$boundary\n";
            $msg .= "Content-Transfer-Encoding: base64\n";
            $clean_filename = mb_substr($file["name"], 0, self::MAX_ATTACHMENT_NAME_LEN);
            $msg .= "Content-Type: {$file['mime']}; name=$clean_filename;\n";
            $msg .= "Content-Disposition: attachment; filename=$clean_filename;\n";
            $msg .= "\n";
            $msg .= base64_encode(file_get_contents($file['filepath']));
            if (($idx + 1) === $count)
                $msg .= "==\n";
            $msg .= "--$boundary";
        }
        // close email
        $msg .= "--\n";
    }

    // now send the email out
    try {
        file_put_contents("log.txt", $msg);
        $ses_result = $client->sendRawEmail(
                array(
            'RawMessage' => array(
                'Data' => base64_encode($msg)
            )
                ), array(
            'Source' => $from,
            'Destinations' => $to_str
                )
        );
        if ($ses_result) {
            $res->message_id = $ses_result->get('MessageId');
        } else {
            $res->success = false;
            $res->result_text = "Amazon SES did not return a MessageId";
        }
    } catch (Exception $e) {
        $res->success = false;
        $res->result_text = $e->getMessage().
                " - To: $to_str, Sender: $from, Subject: $subject";
    }
    return $res;
}

private static function getParam($params, $param, $required = false) {
    $value = isset($params[$param]) ? $params[$param] : null;
    if ($required && empty($value)) {
        throw new Exception('"'.$param.'" parameter is required.');
    } else {
        return $value;
    }
}

}

class ResultHelper {

    public $success = true;
    public $result_text = "";
    public $message_id = "";

}

?>

And the function I'm using to send the actual email以及我用来发送实际电子邮件的功能

function sendAttachmentEmail($from, $to, $subject, $message, $attachmentPaths=array()){
    client = SesClient::factor(array('key' => SES_KEY, 'secret' => SES_SECRET, 'region' => 'us-east-1'));
    $attachments = array();
    foreach($attachmentPaths as $path){
        $fileName = explode("/",, $path);
        $fileName = $fileName[count($fileName)-1];
        $extension = explode(".", $fileName);
        $extension = strtoupper($extension[count($extension)-1]);
        $mimeType = "";
        if($extension == 'PDF') $mimeType = 'application/pdf';
        elseif($extension == 'CSV') $mimeType = 'test/csv';
        elseif($extension == 'XLS') $mimeType = 'application/vnd.ms-excel';
        array_push($attachments, array("name" => $fileName, "filepath" => $path, "mime" => $mimeType));
    }
    $params = array(
        "from" => $from,
        "to" => $to,
        "subject" => $subject,
        "message" => $message,
        "replyTo" => $from,
        "files" => $attachments
    );
    $res = SESUtils::sendMail($params);
    return $res;
}

sendAttachmentEmail("jesse@aol.com", "jesse@aol.com", 'test', 'test', array("/path/to/file.pdf"));

When I run this the message returned is an error saying "Expected ';', got "Reports" - To: jesse@aol.com, Sender: jesse@aol.com, Subject: test" .当我运行此程序时,返回的消息是一条错误消息,指出"Expected ';', got "Reports" - To: jesse@aol.com, Sender: jesse@aol.com, Subject: test" Anyone know what I might be missing?有谁知道我可能会错过什么? The contents of the msg being sent is发送的消息内容是

To: jesse@aol.com
From: jesse@aol.com
Reply-To: jesse@aol.com
Subject: test
MIME-Version: 1.0
Content-Type: multipart/alternative;
 boundary="_Part_142255491754ca7725b0bf89.40746157"

--_Part_142255491754ca7725b0bf89.40746157
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit

test
--_Part_142255491754ca7725b0bf89.40746157
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 7bit

test
--_Part_142255491754ca7725b0bf89.40746157
Content-Transfer-Encoding: base64
Content-Type: application/pdf; name=file.pdf;
Content-Disposition: attachment; filename=file.pdf;

Here is my working solution for PHP 7 using V3.x of AWS PHP SDK.这是我使用 AWS PHP SDK V3.x 的 PHP 7 工作解决方案。 This solution will send a HTML mail with one attachment:此解决方案将发送一封带有一个附件的 HTML 邮件:

use Aws\Ses\SesClient;

$gAWS_SES_client = SesClient::factory(array(
    'version'=> 'latest',
    'region' => 'eu-west-1',
    'credentials' => array(
        'key' => 'my_secret_key',
        'secret'  => 'my_secret_pw'
  ) 
));



function sendRAWEmailViaSES($myArrayToAdresses, $myFromAdress, $mySubject, $myHTMLBody, $myFilePath){
    global $gAWS_SES_client;

    echo "\n<BR>Now in sendRAWEmailViaSES()<BR>\n";

    $myStringToAddresses = implode(",", $myArrayToAdresses);

    $myFileName = basename($myFilePath);;

    $myDataAttachedFile = file_get_contents($myFilePath);
    $myDataAttachedFile = chunk_split(base64_encode($myDataAttachedFile));  

    $myFileMimeInfo = finfo_open(FILEINFO_MIME_TYPE);
    $myFileMimeType = finfo_file($myFileMimeInfo, $myFilePath);     

    $mySeparator = md5(time());
    $mySeparator_multipart = md5($mySubject . time());      

    $myMessage = "";

    $myMessage .= "MIME-Version: 1.0\n";

    $myMessage .= "To: ".$myStringToAddresses."\n"; 
    $myMessage .= "From:".$myFromAdress."\n";   
    $myMessage .= "Subject:".$mySubject."\n";

    $myMessage .= "Content-Type: multipart/mixed; boundary=\"".$mySeparator_multipart."\"\n";
    $myMessage .= "\n--".$mySeparator_multipart."\n";

    $myMessage .= "Content-Type: multipart/alternative; boundary=\"".$mySeparator."\"\n";
    $myMessage .= "\n--".$mySeparator."\n";

    $myMessage .= "Content-Type: text/html; charset=\"UTF-8\"\n";
    $myMessage .= "\n".$myHTMLBody."\n";
    $myMessage .= "\n--".$mySeparator."--\n";

    $myMessage .= "--".$mySeparator_multipart."\n";
    $myMessage .= "Content-Type: ".$myFileMimeType."; name=\"".$myFileName."\"\n";
    $myMessage .= "Content-Disposition: attachment; filename=\"".$myFileName."\"\n";
    $myMessage .= "Content-Transfer-Encoding: base64\n\n";
    $myMessage .= $myDataAttachedFile."\n";
    $myMessage .= "--".$mySeparator_multipart."--";

    //echo "\n<BR>Message:<BR>\n";
    //print_r($myMessage);
    //echo "<BR>\n";        


    $myArraySES = [
        'Source'       => $myFromAdress,
        'Destinations' => $myArrayToAdresses,
        'RawMessage'   => [
            'Data' => $myMessage
        ]
    ];  

    echo "\n<HR>Trying to send mail via AAWS SES <BR>\n";


    try{
        $myResult = true;
        $myAPIResult = $gAWS_SES_client->sendRawEmail($myArraySES);

        //save the MessageId which can be used to track the request
        //$myMessageArrayID = $myAPIResult->get('MessageId');
        //echo("MessageId: $msg_id");

        //view sample output
        echo "\n<BR>SES Result:<BR>\n";
        print_r($myAPIResult);
        echo "<BR>\n";

    } catch (Exception $myObjError) {
        //An error happened and the email did not get sent
        $myErrorInfo = $myObjError->getMessage();

        echo "\n<BR>*** SES ERROR:<BR>\n";
        print_r($myErrorInfo);
        echo "<BR>\n";      

        $myfile = fopen("ses_send_error.txt", "w");
        fwrite($myfile, $myErrorInfo);
        fclose($myfile);

    }   


}

Late but i hope this could help others.迟到了,但我希望这可以帮助其他人。

The best way to achieve this goal is using PHPMailer to compose the email and get the MIMEMessage to pass it as RawMessage to AWS SES client .实现此目标的最佳方法是使用PHPMailer撰写电子邮件并获取MIMEMessage以将其作为RawMessage传递给AWS SES 客户端


Installation with composer:使用 Composer 安装:

$ composer require phpmailer/phpmailer

PHPMailer naive example: PHPMailer 天真示例:

// Create PHPMailer instance
$mail = new \PHPMailer\PHPMailer\PHPMailer;

// Set the email values
$mail->setFrom("foo@bar.com", "Jhon Doe");
$mail->addAddress("destination@somedomain.com");
$mail->Subject = "Hi There ! ";
$mail->Body = <<<EOS
Your email content, <br>
you can write it even as a <strong>HTML document</strong>
EOS;
$mail->AltBody = <<<EOS
Your email content, here you write plain text body for clients that do not support html.
EOS;

// Here you attach your file or files
// @string path
// @string file_name. If not specified, it takes the original name from the path.
$mail->addAttachment("/path/to/file.xlsx", 'my_file.xlsx');

// Here is the magic
$mail->preSend();
$rawMessage = $mail->getSentMIMEMessage();

Now, you can pass the MIMEMessage to the sendRawEmail method in the SES SDK现在,您可以将 MIMEMessage 传递给 SES SDK 中的 sendRawEmail 方法

$credentials = new Aws\Credentials\Credentials('XXXXX', 'YYYYYYYYYYY');
$ses_client = new Aws\Ses\SesClient([
        'credentials' => $credentials,
        'version' => '2010-12-01',
        'region'  => 'us-west-2'
]);


$ses_client->sendRawEmail([
            "RawMessage" => [
                "Data" => $rawMessage
            ]
]);

That's it !就是这样 !

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM