AWS SES SendEmail specifying a name gives 403 Forbidden response - php

I am trying to set up a mail system with Amazon SES service. All is good and working if I use only the email address in "Source" parameter. If I try to add a name, I get a 403 Forbidden HTTP error.
In my PHP code I use AWS SDK:
$client = Aws\Ses\SesClient::factory(array(
'key' => 'MYAWSKEYXXXXXXXXXX',
'secret' => 'MYAWSSECRETXXXXXXXXXXX',
'version'=> 'latest',
'region' => 'us-east-1'
));
$request = array();
$request['Source'] = "sender#example.com";
$request['Destination']['ToAddresses'] = array("receiver#example.com");
$request['Message']['Subject']['Data'] = 'Mail Subject';
$request['Message']['Body']['Html']['Data'] = 'mail body in HTML: <b>Hello!</b>';
try {
$result = $client->sendEmail($request);
$messageId = $result->get('MessageId');
$message = "Email sent! Message ID: $messageId";
} catch (Exception $e) {
$message = "The email was not sent. Error message: ";
$message .= $e->getMessage();
}
This code works great, because I have correctly set up my email source in the AWS console with the correct policy. So "sender#example.com" in this example can correctly send the email.
Then, if I try to add a name to the "Source" param, I don't have any success. I tried:
$request['Source'] = "My Name <sender#example.com>";
OR
$request['Source'] = "'My Name' <sender#example.com>";
OR
$request['Source'] = "'My Name'<sender#example.com>";
OR
$request['Source'] = "'My Name <sender#example.com>'";
OR
$request['Source'] = '"My Name" <sender#example.com>';
OR
$request['Source'] = '"My Name"<sender#example.com>';
OR
$request['Source'] = '"My Name <sender#example.com>"';
None of the above work.
Does anybody have any idea on how to use SES sendEmail with email names?
Some answers I saw here, like this one, simply don't work. I need to use sendEmail and PHP SDK.

Related

Amazon SES RawMessage: Missing required header 'From'

use PHPMailer\PHPMailer\PHPMailer;
use Aws\Ses\SesClient;
use Aws\Ses\Exception\SesException;
require 'vendor/autoload.php';
if(!function_exists("sendmailalexraw")){
function sendmailalexraw($email,$subject,$messages,$definesender)
{
// Replace sender#example.com with your "From" address.
// This address must be verified with Amazon SES.
$sender = $definesender;
$sendername = 'Alex';
// Replace recipient#example.com with a "To" address. If your account
// is still in the sandbox, this address must be verified.
$recipient = $email;
// Specify a configuration set.
$configset = 'ConfigSet';
// Replace us-west-2 with the AWS Region you're using for Amazon SES.
$region = 'eu-west-1';
$subject = $subject;
$htmlbody = <<<EOD
<html>
<head></head>
<body>
<h1>Hello!</h1>
<p>Please see the attached file for a list of customers to contact.</p>
</body>
</html>
EOD;
$textbody = <<<EOD
Hello,
Please see the attached file for a list of customers to contact.
EOD;
//// The full path to the file that will be attached to the email.
$att = 'path/to/customers-to-contact.xlsx';
// Create an SesClient.
$client = SesClient::factory(array(
'version'=> 'latest',
'region' => $region
));
// Create a new PHPMailer object.
$mail = new PHPMailer;
// Add components to the email.
$mail->setFrom($sender, $sendername);
$mail->addAddress($recipient);
$mail->Subject = $subject;
$mail->Body = $htmlbody;
$mail->AltBody = $textbody;
$mail->addAttachment($att);
$mail->addCustomHeader('X-SES-CONFIGURATION-SET', $configset);
// Attempt to assemble the above components into a MIME message.
if (!$mail->preSend()) {
echo $mail->ErrorInfo;
} else {
// Create a new variable that contains the MIME message.
$message = $mail->getSentMIMEMessage();
}
// Try to send the message.
try {
$result = $client->sendRawEmail([
'RawMessage' => [
'Data' => $messages
]
]);
// If the message was sent, show the message ID.
$messageId = $result->get('MessageId');
echo("Email sent! Message ID: $messageId"."\n");
} catch (SesException $error) {
// If the message was not sent, show a message explaining what went wrong.
echo("The email was not sent. Error message: "
.$error->getAwsErrorMessage()."\n");
}
}
}
$email='example#gmail.com';
$subject='abc';
$messages='xyz';
$definesender='info#verifieddomain.net';
sendmailalexraw($email,$subject,$messages,$definesender);
?>
I am trying to send RawMessage with Amazon SES but I get :
The email was not sent. Error message: Missing required header 'From'.
Sender I use it's verified, my Amazon SES it's active (out of sendbox ) .
I am needing to send as RAW Message to create unsubscribe option for emails I am sening. As I read from documentation it have to be raw email to be able to add this parameters.Thank you !
You have to base64 encode the message :
$result = $client->sendRawEmail([
'RawMessage' => [
'Data' => base64_encode($messages)
]
]);
Since you're using AWS Ses, you could do it this way:
define('SENDER', 'Your name<a#a.com>');
define('RECIPIENT', 'b#b.com');
define('CCLIST', 'c#c.com');
define('REGION','your region');
define('SUBJECT','Your subject goes here');
$bodytext = "<h2>Your body goes here.</h2>" . PHP_EOL;
$bodytext .= "<p>Append as many rows as you want</p>";
define('BODY',$bodytext);
$client = SesClient::factory(array(
'version'=> 'latest',
'region' => 'your region'
));
$request = array();
$request['Source'] = SENDER;
$request['Destination']['ToAddresses'] = array(RECIPIENT);
$request['Destination']['CcAddresses'] = array(CCLIST);
$request['Message']['Subject']['Data'] = SUBJECT;
$request['Message']['Body']['Html']['Data'] = BODY;
try {
$result = $client->sendEmail($request);
$messageId = $result->get('MessageId');
echo("Email successfully sent! Message ID: $messageId"."\n");
} catch (Exception $e) {
echo("The email was not sent. Error message: ");
echo($e->getMessage()."\n");
}

Sendgrid php send to multiple recipients

I have simple sendgrid php script to send email, only issue here is that i need to add more recipients, so this code works only for one recipient, i was looking at official documentation but was unable to find any useful info, is there anyone who knows how and what i need to change here to add more recipients/emails.
function sendEmail($subject, $to, $message) {
$from = new SendGrid\Email(null, "sample#email.com");
$subject = $subject;
$to = new SendGrid\Email(null, $to);
$content = new SendGrid\Content("text/html", $message);
$mail = new SendGrid\Mail($from, $subject, $to, $content);
$apiKey = 'MY_KEY';
$sg = new \SendGrid($apiKey);
$response = $sg->client->mail()->send()->post($mail);
echo $response->statusCode();
}
The SendGrid\Mail class supports adding multiple to addresses through the SendGrid\Personalization class.
You can see an example here: https://github.com/sendgrid/sendgrid-php/blob/master/examples/helpers/mail/example.php#L31-L35
Think of a Personalization as the envelope for your email. It holds the recipient's addresses and other similar data. Each Sendgrid\Mail object, must have at least one Personalization.
Through the constructor you are using, a Personalization object is already created for you, see here: https://github.com/sendgrid/sendgrid-php/blob/master/lib/helpers/mail/Mail.php#L951-L958
You can create a Mail object without this and later add your own Personalization.
In the end, this is how I have managed to do this and it's working good.
function sendEmail($subject, $to, $message, $cc)
{
$from = new SendGrid\Email(null, "sample#email.com");
$subject = $subject;
$to = new SendGrid\Email(null, $to);
$content = new SendGrid\Content("text/html", $message);
$mail = new SendGrid\Mail($from, $subject, $to, $content);
foreach ($cc as $value) {
$to = new SendGrid\Email(null, $value);
$mail->personalization[0]->addCC($to);
}
$apiKey = 'MY_KEY';
$sg = new \SendGrid($apiKey);
$response = $sg->client->mail()->send()->post($mail);
echo $response->statusCode();
}
If someone is still looking for an answer to how to add multiple emails in To, Cc, and Bcc, Using SendGrid, here is what helped me.
First, you need to add an associative array like this:
for multiple emails in to (recipients):
$tos = [
"example1#example.com" => "User 1",
"example1#example.com" => "User 2"
];
and in your SendMail class use this $email->addTos($tos); instead of $email->addTo;
Similarly, for multiple Cc use
$email->addCcs($cc);
and for Bcc
$email->addBccs($bcc);
Here is the link to see more details sendgrid php
function makeEmail($to_emails = array(),$from_email,$subject,$body) {
$from = new SendGrid\Email(null, $from_email);
$to = new SendGrid\Email(null, $to_emails[0]);
$content = new SendGrid\Content("text/plain", $body);
$mail = new SendGrid\Mail($from, $subject, $to, $content);
$to = new SendGrid\Email(null, $to_emails[1]);
$mail->personalization[0]->addTo($to);
return $mail;
}
function sendMail($to = array(),$from,$subject,$body) {
$apiKey = 'your api key';
$sg = new \SendGrid($apiKey);
$request_body = makeEmail($to ,$from,$subject,$body);
$response = $sg->client->mail()->send()->post($request_body);
echo $response->statusCode();
echo $response->body();
print_r($response->headers());
}
$to = array('test1#example.com','test2#example.com');
$from = 'from#example.com';
$subject = "Test Email Subject";
$body = "Send Multiple Person";
sendMail($to ,$from,$subject,$body);
Now Sendgrid provides an easy way for sending single mail to multiple recipients,
it provides Mail::addTos method in which we can add multiple mails to whom we want to send our mail,
we have to pass associative array of user emails and user names into addTos.
see below example:
$tos = [
//user emails => user names
"user1#example.com" => "Example User1",
"user2#example.com" => "Example User2",
"user3#example.com" => "Example User3"
];
$email->addTos($tos);
If you want to see Full example which is provided in sendgrid-php github library then i have included it below, so you can understand the whole example:
<?php
require 'vendor/autoload.php'; // If you're using Composer (recommended)
// Comment out the above line if not using Composer
// require("<PATH TO>/sendgrid-php.php");
// If not using Composer, uncomment the above line and
// download sendgrid-php.zip from the latest release here,
// replacing <PATH TO> with the path to the sendgrid-php.php file,
// which is included in the download:
// https://github.com/sendgrid/sendgrid-php/releases
$email = new \SendGrid\Mail\Mail();
$email->setFrom("test#example.com", "Example User");
$tos = [
"test+test1#example.com" => "Example User1",
"test+test2#example.com" => "Example User2",
"test+test3#example.com" => "Example User3"
];
$email->addTos($tos);
$email->setSubject("Sending with Twilio SendGrid is Fun");
$email->addContent("text/plain", "and easy to do anywhere, even with PHP");
$email->addContent(
"text/html", "<strong>and easy to do anywhere, even with PHP</strong>"
);
$sendgrid = new \SendGrid(getenv('SENDGRID_API_KEY'));
try {
$response = $sendgrid->send($email);
print $response->statusCode() . "\n";
print_r($response->headers());
print $response->body() . "\n";
} catch (Exception $e) {
echo 'Caught exception: '. $e->getMessage(). "\n";
}
Ref:
https://github.com/sendgrid/sendgrid-php/blob/master/USE_CASES.md#send-an-email-to-multiple-recipients

GAE InvalidArgumentException with Mail Service Error

This is not a duplicate question I have tried a lot with GAE Php mail send but find exception below is not an authorized email address. I have tried with all email ids.
ot sendexception 'InvalidArgumentException' with message 'Mail Service Error: Sender (info#mywebsite.in) is not an authorized email address.' in /base/data/home/runtimes/php/sdk/google/appengine/api/mail/BaseMessage.php:336 Stack trace: #0 /base/data/home/runtimes/php/sdk/google/appengine/api/mail/Message.php(148): google\appengine\api\mail\BaseMessage->handleApplicationError(Object(google\appengine\runtime\ApplicationError)) #1 /base/data/home/apps/s~acuteservice-1260/1.393973634644018844/contact.php(38): google\appengine\api\mail\Message->send() #2 {main}
Below is my code that through above InvalidArgumentException
<?php
use google\appengine\api\mail\Message;
$name=$email=$query="";
if($_SERVER["REQUEST_METHOD"]=="POST"){
$name = $_POST["name"];
$email = $_POST["email"];
$query = $_POST["message"];
require_once 'google/appengine/api/mail/Message.php';
$mail_options = [
"sender" => "info#mywebsite.in",
"to" => "isashi4u#gmail.com",
"subject" => "Subject",
"textBody" => $query,
];
try {
$message = new Message($mail_options);
$message->send();
} catch (InvalidArgumentException $e) {
echo "not send";
echo $e;
}
}?>
is there any way to give default setting on "sender" mail_option ?

send email using gmail-api and google-api-php-client

I am using https://github.com/google/google-api-php-client and I want to send a test email with a user's authorized gmail account.
This is what I have so far:
$msg = new Google_Service_Gmail_Message();
$msg->setRaw('gp1');
$service->users_messages->send('me', $msg);
This results in a bounce email because I have no clue how to set the raw message. I see the bounce in the inbox of my authenticated user. I want to learn how to set values for 'To', 'Cc', 'Bcc', 'Subject', and 'Body' of the email. I believe I will need to do a 64 encoding on that raw data as well. And I might want to use some html in the body of my email.
Please help to provide a working example of sending an email using the gmail-api and the google-api-php-client.
Here is the bounced email in the inbox:
Bounce -nobody#gmail.com- 12:58 PM (7 minutes ago)
to me
An error occurred. Your message was not sent.
‚ Date: Thu, 24 Jul 2014 10:58:30 -0700 Message-Id: CABbXiyXhRBzzuaY82i9iODEiwxEJWO1=jCcDM_TH-
I asked a more specific question which has led me to an answer. I am now using PHPMailer to build the message. I then extract the raw message from the PHPMailer object. Example:
require_once 'class.phpmailer.php';
$mail = new PHPMailer();
$mail->CharSet = "UTF-8";
$subject = "my subject";
$msg = "hey there!";
$from = "myemail#gmail.com";
$fname = "my name";
$mail->From = $from;
$mail->FromName = $fname;
$mail->AddAddress("tosomeone#somedomain.com");
$mail->AddReplyTo($from,$fname);
$mail->Subject = $subject;
$mail->Body = $msg;
$mail->preSend();
$mime = $mail->getSentMIMEMessage();
$m = new Google_Service_Gmail_Message();
$data = base64_encode($mime);
$data = str_replace(array('+','/','='),array('-','_',''),$data); // url safe
$m->setRaw($data);
$service->users_messages->send('me', $m);
I've used this solution as well, worked fine with a few tweaks:
When creating the PHPMailer object, the default encoding is set to '8bit'.
So I had to overrule that with:
$mail->Encoding = 'base64';
The other thing i had to do was tweaking the MIME a little to make it POST ready for the Google API, I've used the solution by ewein:
Invalid value for ByteString error when calling gmail send API with base64 encoded < or >
Anyway, this is how I've solved your problem:
//prepare the mail with PHPMailer
$mail = new PHPMailer();
$mail->CharSet = "UTF-8";
$mail->Encoding = "base64";
//supply with your header info, body etc...
$mail->Subject = "You've got mail!";
...
//create the MIME Message
$mail->preSend();
$mime = $mail->getSentMIMEMessage();
$mime = rtrim(strtr(base64_encode($mime), '+/', '-_'), '=');
//create the Gmail Message
$message = new Google_Service_Gmail_Message();
$message->setRaw($mime);
$message = $service->users_messages->send('me',$message);
Perhaps this is a bit beyond the original question, but at least in my case that "test email" progressed to regularly sending automated welcome emails "from" various accounts. Though I've found much that is helpful here, I've had to cobble things together from various sources.
In the hope of helping others navigate this process, here's a distilled version of what I came up with.
A few notes on the following code:
This assumes that you've jumped through the hoops to create and download the JSON for a Google Service Account (under credentials in the developer dashboard it's the bottom section.)
For clarity, I've grouped all the bits you should need to set in the "Replace this with your own data" section.
That me in the send() method is a key word that means something like "send this email with the current account."
// This block is only needed if you're working outside the global namespace
use \Google_Client as Google_Client;
use \Google_Service_Gmail as Google_Service_Gmail;
use \Google_Service_Gmail_Message as Google_Service_Gmail_Message;
// Prep things for PHPMailer
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\PHPMailer;
// Grab the needed files
require_once 'path/to/google-api/vendor/autoload.php';
require_once 'path/to/php-mailer/Exception.php';
require_once 'path/to/php-mailer/PHPMailer.php';
// Replace this with your own data
$pathToServiceAccountCredentialsJSON = "/path/to/service/account/credentials.json";
$emailUser = "sender#yourdomain.com"; // the user who is "sending" the email...
$emailUserName = "Sending User's Name"; // ... and their name
$emailSubjectLine = "My Email's Subject Line";
$recipientEmail = "recipient#somdomain.com";
$recipientName = "Recipient's Name";
$bodyHTML = "<p>Paragraph one.</p><p>Paragraph two!</p>";
$bodyText = "Paragraph one.\n\nParagraph two!";
// Set up credentials and client
putenv("GOOGLE_APPLICATION_CREDENTIALS={$pathToServiceAccountCredentialsJSON}");
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
// We're only sending, so this works fine
$client->addScope(Google_Service_Gmail::GMAIL_SEND);
// Set the user we're going to pretend to be (Subject is confusing here as an email also has a "Subject"
$client->setSubject($emailUser);
// Set up the service
$mailService = new Google_Service_Gmail($client);
// We'll use PHPMailer to build the raw email (since Google's API doesn't do that) so prep it
$mailBuilder = new PHPMailer();
$mailBuilder->CharSet = "UTF-8";
$mailBuilder->Encoding = "base64";
// Not set up the email you want to send
$mailBuilder->Subject = $emailSubjectLine;
$mailBuilder->From = $emailUser;
$mailBuilder->FromName = $emailUserName;
try {
$mailBuilder->addAddress($recipientEmail, $recipientName);
} catch (Exception $e) {
// Handle any problems adding the email address here
}
// Add additional recipients, CC, BCC, ReplyTo, if desired
// Then add the main body of the email...
$mailBuilder->isHTML(true);
$mailBuilder->Body = $bodyHTML;
$mailBuilder->AltBody = $bodyText;
// Prep things so we have a nice, raw message ready to send via Google's API
try {
$mailBuilder->preSend();
$rawMessage = base64_encode($mailBuilder->getSentMIMEMessage());
$rawMessage = str_replace(['+', '/', '='], ['-', '_', ''], $rawMessage); // url safe
$gMessage = new Google_Service_Gmail_Message();
$gMessage->setRaw($rawMessage);
// Send it!
$result = $mailService->users_messages->send('me', $gMessage);
} catch (Exception $e) {
// Handle any problems building or sending the email here
}
if ($result->labelIds[0] == "SENT") echo "Message sent!";
else echo "Something went wrong...";
Create the mail with phpmailer works fine for me in a local enviroment. On production I get this error:
Invalid value for ByteString
To solve this, remove the line:
$mail->Encoding = 'base64';
because the mail is two times encoded.
Also, on other questions/issues I found the next:
use
strtr(base64_encode($val), '+/=', '-_*')
instead of
strtr(base64_encode($val), '+/=', '-_,')
I Used https://developers.google.com/gmail/api/v1/reference/users/messages/send
and able to send email successfully.

SwiftMailer Error

So I am trying to setup swift mailer to work with the Mandrill API, but it keeps throwing the following error:
Failures:Array ( [0] => example#email.com ) (I have a proper email in this place in my code)
My code is as follows:
$subject = 'Hello from Mandrill, PHP!';
// approved domains only!
$from = array('example2#email.com' =>'Your Name');
$to = array(
'example#email.com' => 'Recipient1 Name'
);
$text = "Mandrill speaks plaintext";
$html = "Mandrill speaks HTML";
$transport = Swift_SmtpTransport::newInstance('smtp.mandrillapp.com', 587);
$transport->setUsername(getenv('my#mandrillemail.com'));
$transport->setPassword(getenv('mymandrillpass'));
$swift = Swift_Mailer::newInstance($transport);
$message = new Swift_Message($subject);
$message->setFrom($from);
$message->setBody($html, 'text/html');
$message->setTo($to);
$message->addPart($text, 'text/plain');
// Pass a variable name to the send() method
if (!$swift->send($message, $failures))
{
echo "Failures:";
print_r($failures);
}
What is going wrong?
Try using SSL and port 465.
$xport = Swift_SmtpTransport::newInstance('smtp.mandrillapp.com', 465, 'ssl');
$xport->setUsername('mandrilluser')
->setPassword('mandrillpass');
See if this works for you.
My problem ended up being that I had to change from using the actual Mandrill account password to the API in the ->setPassword() variable.
Since this is purely an error with your credentials, cross check if the password you are using is actually the token generated by Mandrill or not .
Password doesn't mean the 'password' of your account !!

Categories