无法使用Amazon SES发送电子邮件

3

我正在使用AWS PHP SDK。我有以下代码来使用SES发送电子邮件:

$ses = new AmazonSES(...);
$response =  $ses->send_email('ubuntu@localhost', 
            array('ToAddresses' => 'myemail@somedomain.com'), 
            array( 
                'Subject.Data' => 'My Test message',
                'Body.Text.Data' => 'my message'
            )
        );

很简单,对吧?但是我从AWS SDK本身得到以下错误:

Undefined index: body

sdk.class.php(828)

// Normalize JSON input
828         if ($query['body'] === '[]')
829         {
830             $query['body'] = '';
831         }

我的AWS访问密钥和秘密密钥是正确的,因为我能够使用S3。我错过了什么?

编辑: 我在@gamil.com上验证了另一个电子邮件地址,并将其用作发件人地址。我仍然遇到了最初报告的错误。不过,我使用提到的第三方库没有问题。


你应该得到一个真正的错误,但是你是否已经验证了发送的收件人和发件人地址?在开发沙盒中,您需要这样做。此外,SES非常新,我认为他们上周推出了SDK的新版本,所以值得检查一下... - Charles
我应该如何验证电子邮件地址? 我已添加$ses->verify_email_address的调用,但没有任何更改。 ubuntu@localhost是我在本地ubuntu实例上运行的用户。 - Simian
它必须是一个SES可以发送邮件到的公开可访问的电子邮件地址。 - Skyler Johnson
4个回答

8

更新:此漏洞已得到修复! 请下载最新版本。

这似乎是Amazon SDK中的一个已确认的漏洞。请参见下面的链接...

https://forums.aws.amazon.com/thread.jspa?messageID=231411

据我所知,目前还没有补丁可用。我想你可以使用isset()自己打补丁。这就是我所做的,现在看起来好像可以工作了。再次提醒,这是sdk.class.php第828行的一个漏洞。我现在不想制作补丁文件。以下是我对代码所做的修改...

// Normalize JSON input
if (!isset($query['body']) || $query['body'] === '[]')
{
    $query['body'] = '';
}

虽然这不是官方补丁,但它可以让你继续愉快地使用。


1

以下是我如何在没有SDK的情况下完成它:

<?php

error_reporting(E_ALL);
ini_set('display_errors','On');

// AMAZON PARAMETERS
$sAccess = 'YOUR-ACCESS-KEY-GOES-HERE';
$sSecret = 'YOUR-SECRET-KEY-GOES-HERE';
$sURL = 'https://email.us-east-1.amazonaws.com/'; // may be subject to change!
$nVerifyHost = 1; // may need to set either of these to 0 on some hosting plans
$nVerifyPeer = 1;

// OUR TEST MESSAGE
$sTo = 'you@example.com'; // must request production mode in AWS SES Console
$sFrom = 'sender@example.com'; // must verify the sender in the AWS SES Console
$sSubject = 'Hello, World!';
$sMessage = <<<EOD
<p>This is para 1.</p>

<p>This is para 2.</p>

<p>Regards,<br>
<b>Management</b></p>
EOD;

// SEND THE MESSAGE
$sDate = gmdate('D, d M Y H:i:s e');
$sSig = base64_encode(hash_hmac('sha256', $sDate, $sSecret, TRUE));
$asHeaders = array();
$asHeaders[] = 'Date: ' .  $sDate;
$asHeaders[] = 'X-Amzn-Authorization: AWS3-HTTPS AWSAccessKeyId=' . $sAccess . 
  ',Algorithm=HmacSHA256,Signature=' . $sSig;
$asHeaders[] = 'Content-Type: application/x-www-form-urlencoded';
$sText = $sMessage;
$sText = str_replace("\r\n",'',$sText);
$sText = str_replace("\r",'',$sText);
$sText = str_replace("\n",'',$sText);
$sText = str_replace("\t",'  ',$sText);
$sText = str_replace('<BR />','<br />',$sText);
$sText = str_replace('<BR/>','<br />',$sText);
$sText = str_replace('<BR>','<br />',$sText);
$sText = str_replace('</P>','</p>',$sText);
$sText = str_replace('</p>',"</p>\n\n",$sText);
$sText = str_replace('<br />',"<br />\n",$sText);
$sText = strip_tags($sText);
$asQuery = array(
  'Action' => 'SendEmail',
  'Destination.ToAddresses.member.1' => $sTo,
  'Source' => $sFrom,
  'Message.Subject.Data' => $sSubject,
  'Message.Body.Text.Data' => $sText,
  'Message.Body.Html.Data' => $sMessage
);
$sQuery = http_build_query($asQuery);

$hCurl = curl_init();
curl_setopt($hCurl, CURLOPT_SSL_VERIFYHOST, $nVerifyHost);
curl_setopt($hCurl, CURLOPT_SSL_VERIFYPEER, $nVerifyPeer);
curl_setopt($hCurl, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($hCurl, CURLOPT_POSTFIELDS, $sQuery);
curl_setopt($hCurl, CURLOPT_HTTPHEADER, $asHeaders);
curl_setopt($hCurl, CURLOPT_HEADER, 0);
curl_setopt($hCurl, CURLOPT_URL, $sURL);
curl_setopt($hCurl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($hCurl, CURLOPT_FOLLOWLOCATION, 1);

$asResult = array('code'=>'','error'=>'');
if (curl_exec($hCurl)) {
  $asResult['code'] = curl_getinfo($hCurl, CURLINFO_HTTP_CODE);
} else {
  $asResult['error'] = array (
    'code' => curl_errno($hCurl),
    'message' => curl_error($hCurl),
  );
}
@curl_close($hCurl);
print_r($asResult);

我该如何使用你的逻辑发送大量邮件? - cawecoy
@cawecoy 或许使用 Mailgun 发送大量邮件会更容易些。 - Volomike

1

我猜你需要一个非私人的电子邮件地址,而ubuntu@localhost显然不是。

(编辑) 此外,根据文档,您需要验证您是该电子邮件地址的所有者,而您显然无法使用ubuntu@localhost进行验证。

电子邮件地址验证

在您发送第一封邮件之前,Amazon SES要求您验证您的电子邮件地址。这是为了确认您拥有该电子邮件地址,并防止他人使用它。

http://docs.amazonwebservices.com/es/latest/DeveloperGuide/index.html?InitialSetup.EmailVerification.html


是的,我已经添加了使用外部电子邮件地址进行验证的调用。问题仍然存在,我从未收到过验证电子邮件。 - Simian
@Simian 因为如果您尝试验证 ubuntu@localhost,那么 localhost 将是亚马逊 SES 服务器地址,而您的帐户不在那里。 - Steve-o
不,我的意思是我在 @gmail.com 上验证了另一个电子邮件地址,并将其用作发件人地址。但我仍然遇到了最初报告的错误。不过,我使用了我提到的第三方库没有任何问题。 - Simian

0

发现这个SDK非常缓慢,导致FastCGI超时。我试图一次发送大约500封电子邮件,但在30到40之间超时。已经请求帮助解决这个问题... - andrebruton
@andrebruton,您的超时问题可能是由于发送限制和/或 PHP 页面时间限制导致的。您可能无法每秒发送超过 5 封电子邮件。您应该考虑添加 usleep() 命令,例如每隔 5 封电子邮件执行一次。此外,在 PHP 中使用 set_time_limit(),但某些托管计划会阻止您延长多长时间 - 您可能需要更灵活的托管计划。最后,请考虑使用队列表和 cron 发送邮件。 - Volomike

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接