How to get delivery report info on AWS SNS using PHP? - php

I am using the AWS php SDK to send SNS messages. I am using APNS. I have followed the SDK examples, no problems there. Most of my messages are getting sent, but some appear to be failing. According to the SNS doc, if I get a message ID back - which I am every single time - then the message has been saved to the queue. How do I get more detailed information about these failed messages? The messages are obviously failing in the attempt to send between AWS and APNS.
$result = $client->publish(array(
'TopicArn' => 'string',
'TargetArn' => 'string',
// Message is required
'Message' => 'string',
'Subject' => 'string',
'MessageStructure' => 'string',
));

Related

AWS ses sendEmail php sdk error Email address not verified

I am attempting to send an email through AWS SES using the php sdk. Please note that I am able to send a message through the aws CLI - no problem, and I am able to send an email from the SES console using the domain and email areas under Identity Management area. Also, both the domain and email have been verified and appear in the Identity Management area.
I am using the example code from the PHP SDK. I did edit the region as my emails and domains have been verified, and I operate out of the us-west-2 region.
<?php
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
require 'vendor/autoload.php';
use Aws\Ses\SesClient;
use Aws\Exception\AwsException;
$SesClient = new Aws\Ses\SesClient([
'profile' => 'default',
'version' => '2010-12-01',
'region' => 'us-west-2'
]);
$html_body = '<h1>AWS Amazon Simple Email Service Test Email</h1>' .
'<p>This email was sent with <a href="https://aws.amazon.com/ses/">' .
'Amazon SES</a> using the <a href="https://aws.amazon.com/sdk-for-php/">' .
'AWS SDK for PHP</a>.</p>';
$subject = 'Amazon SES test (AWS SDK for PHP)';
$plaintext_body = 'This email was send with Amazon SES using the AWS SDK for PHP.';
$sender_email = 'email_address';
$recipient_emails = ['email_address'];
$char_set = 'UTF-8';
$configuration_set = 'ConfigSet';
try {
$result = $SesClient->sendEmail([
'Destination' => [
'ToAddresses' => $recipient_emails,
],
'ReplyToAddresses' => [$sender_email],
'Source' => $sender_email,
'Message' => [
'Body' => [
'Html' => [
'Charset' => $char_set,
'Data' => $html_body,
],
'Text' => [
'Charset' => $char_set,
'Data' => $plaintext_body,
],
],
'Subject' => [
'Charset' => $char_set,
'Data' => $subject,
],
],
// If you aren't using a configuration set, comment or delete the
// following line
'ConfigurationSetName' => $configuration_set,
]);
var_dump($result);
} catch (AwsException $e) {
// output error message if fails
echo $e->getMessage();
echo "\n";
}
I am providing the credentials for the SDK through the ~/.aws/credential file, that contains the access ID key and secret key. This is the same file that is accessed by the AWS CLI, so the credentials appear to be correct and accessible to the CLI.
[default]
aws_access_key_id = AKIA2PK........Z72J3
aws_secret_access_key = co9r41j/i+QTrsA7244xG........KPH1LyBn34b
I added the "........" to the above to protect my access and secret access keys.
I get the following error that indicates that my email has not been verified. But it has! Also, I am not in the sandbox mode.
"Error executing "SendEmail" on "https://email.us-west-2.amazonaws.com"; AWS HTTP error: Client error: POST https://email.us-west-2.amazonaws.com resulted in a 400 Bad Request response: Sender MessageReje (truncated...) MessageRejected (client): Email address is not verified. The following identities failed the check in region US-WEST-2: msellers#ranchmed.com - Sender MessageRejected Email address is not verified. The following identities failed the check in region US-WEST-2: msellers#ranchmed.com dbbb0c1d-5493-4205-9257-a2fbb81eb5d9 The email was not sent. Error message: Email address is not verified. The following identities failed the check in region US-WEST-2: msellers#ranchmed.com"
Any ideas on how to debug this?
Appreciate any help that you can provide.
Mark
Found the problem. I hope this helps other aws sdk users. The sdk credential credentials provider found an .aws/credentials file for the webserver user and not from my home directory. In my case, looked in the file /var/cache/nginx/.aws/credentials and found some credentials defined for previous testing purposes.
Lesson is, be aware of how the aws sdk finds the credentials file. If the web server user is set up with a credentials file, then it will use that credential file in preference to one located in your $HOME/.aws/credentials file.

How to send AWS SMS messages to multiple phone numbers in PHP Laravel

I've managed to get my SNS service working in PHP laravel but the issue I have is that I can only send to one number.
I've used the following:
$sms = AWS::createClient('sns');
$sms->publish([
'Message' => $content,
'PhoneNumber' => '+123456789',
'MessageAttributes' => [
'AWS.SNS.SMS.SMSType' => [
'DataType' => 'String',
'StringValue' => 'Transactional',
]
],
]);
The phone number has to be a string, I really do not want to put this inside a for loop for each number and I can't find anything using PHP specifically about sending to multiple phone numbers. Any help would be appreciated!
Hey guys so for anyone interested I managed to find a way to do this. I create a Job queue which I passed the array of phone numbers as well as the content of the message, and then in the handle method in the job just looped through the phone numbers with my above method and it worked perfectly.

Send push notification to multiple devices in single HTTP request with different data for each device using FCM & PHP

As per the official document, we can send push notification to multiple devices using a topic or device group. But the problem is it needs a common message and payload data for all devices.
I want to send different messages to all devices.
For example, below users should receive the following message on their
devices.
User Amit: Hello Amit, your request approved.
User Sandip: Hello Sandip, your request declined.
User Piyush: Hello Piyush, your request declined.
And so on..... to 200-300 users.
Is it possible to send this all messages in a single HTTP request using Firebase Cloud Messaging?
It is possible with the official Admin SDKs (see https://firebase.google.com/docs/cloud-messaging/send-message#send_a_batch_of_messages), but unfortunately, the REST API documentation doesn't include information on how to send batch requests (yet, at least I didn't find them so far), probably because it involves creating a special kind of multipart request and is not easy to set up.
So I would advise using an Admin SDK to do it. As I don't know how you've sent the messages in the past, please be warned that using an Admin SDK comes with some additional setup (e.g. creating/downloading a Service Account), compared to making "just" a cURL request.
So, if you don't have to use PHP, it's always wiser to use one of the official SDKs (see https://firebase.google.com/docs/admin/setup/)
If you do choose to stick with PHP, there is an unofficial Admin SDK for PHP at https://github.com/kreait/firebase-php that supports sending batch messages. (Disclaimer: I'm the maintainer of that SDK).
You can read more about it in the repo or specifically at https://firebase-php.readthedocs.io/en/latest/cloud-messaging.html#send-multiple-messages-at-once, but here is how it might look like for your situation if you decided to give the PHP SDK a try:
use Kreait\Firebase\Factory;
use Kreait\Firebase\Messaging\CloudMessage;
use Kreait\Firebase\Messaging\Notification;
use Kreait\Firebase\ServiceAccount;
$serviceAccount = ServiceAccount::fromJsonFile('/path/to/service_account.json');
$users = [
['name' => 'Amit', 'is_approved' => true, 'registration_token' => '...'],
['name' => 'Sandip', 'is_approved' => false, 'registration_token' => '...'],
['name' => 'Piyush', 'is_approved' => true, 'registration_token' => '...'],
// ...
];
$messages = [];
foreach ($users as $user) {
$statusText = $user['is_approved'] ? 'approved' : 'denied';
$messages[] = CloudMessage::withTarget('token', $user['registration_token'])
->withNotification([
'title' => "Your request was {$statusText}",
'body' => "Hello {$user['name']}! Your request was {$statusText}.",
]);
}
$messaging = (new Factory())
->withServiceAccount($serviceAccount)
->createMessaging();
$sendReport = $messaging->sendAll($messages);
echo 'Successful sends: '.$sendReport->successes()->count().PHP_EOL;
echo 'Failed sends: '.$sendReport->failures()->count().PHP_EOL;
I hope this helps!

AWS SNS Invalid parameter phone number

i am trying to learn aws sns service to send sms from my web application.
I am working on localhost.
$params = array(
'credentials' => array(
'key' => 'iam_key',
'secret' => 'iam_secret',
),
'region' => 'ap-south-1', // < your aws from SNS Topic region
'version' => 'latest',
'http' => ['verify'=>false]
);
$sns = \Aws\Sns\SnsClient::factory($params);
$msgattributes = [
'AWS.SNS.SMS.SenderID' => [
'DataType' => 'String',
'StringValue' => 'Klassroom',
],
'AWS.SNS.SMS.SMSType' => [
'DataType' => 'String',
'StringValue' => 'Transactional',
]
];
$payload = array(
'Message' => "HK test",
"PhoneNumber" => "1234567890",
'MessageAttributes' => $msgattributes
);
$result = $sns->publish($payload);
i want to send sms directly on number. this code is giving this error
Fatal error: Uncaught exception 'Aws\Sns\Exception\SnsException' with message 'Error executing "Publish" on "https://sns.ap-south-1.amazonaws.com"; AWS HTTP error: Client error: POST https://sns.ap-south-1.amazonaws.com resulted in a 400 Bad Request response: Sender InvalidPara (truncated...) InvalidParameter (client): Invalid parameter: PhoneNumber Reason: +1234567890 is not valid to publish to - Sender InvalidParameter Invalid parameter: PhoneNumber Reason: +1234567890 is not valid to publish to 13e181c2-a20f-5e77-9c8e-d38c55c50266 ' exception 'GuzzleHttp\Exception\ClientException' with message 'Client error: POST https://sns.ap-south-1.amazonaws.com resulted in a 400 Bad Request
i don't know why....
I believe a phone number for AWS has to include the country code.
For instance if my phone number is (999) 365-6721 it would be +19993656721 (for US)
I had the exact same issue even though I called the API with a valid phone number prefixed with correct country code (for example +57xxxxxxxxxx).
Then I figured out after running through some threads on the internet that it was only because of the incorrect REGION_CODE (for example us-west-1 instead of us-east-1) used during the instantiation of SNSClient class.
#Bean
public AmazonSNS snsClient() {
return AmazonSNSClientBuilder.standard().withRegion("us-east-1").withCredentials(new AWSStaticCredentialsProvider(credentials())).build();
}
Refer to the link to find the right region code for your case.
You need to use the region that supported SMS for AWS SNS.
More information: https://docs.aws.amazon.com/sns/latest/dg/sms_supported-countries.html
SMS Sandbox Mode
When you start off using SNS for the first time for sending SMS, it starts in the so called 'Sandbox Mode'.
In this mode, you must verify the phone numbers that you intend to use.
If you are using SMS in Sandbox Mode and try to send an SMS via SNS to an unverified number, you will get the error
This prevents unsolicited text messaging.
If you try to create an SMS subscription to an SNS topic without a phone number that's been verified you will indeed receive the error:
Enter a valid mobile number
The phone number is valid. You just need to verify it first, as described above, before you can create this subscription in SNS
Of course, the same principle applies, when you're trying to achieve this via code.

IOS Push notifications with AWS SNS

I have a flash based ios app that I am currently testing on phone/ipod.
I have added push notification to the app and I am receiving device tokens from apple.
I have added those tokens to AWS SNS APN SandBox
The platform Application ARN looks like
arn:aws:sns:us-east-1:7860818154325:app/APNS_SANDBOX/gamename
I have added tokens to the PAA and they look like:
token: f63d05538cd7d9b86c76188dbfeb42edf26a1e23b47334a02a205e0fb54a812a
endpoint ARN: arn:aws:sns:us-east-1:7860818154325:endpoint/APNS_SANDBOX/gamename/7412740a-79e4-3b71-8e7f-56e127bc4cg1
Sending out the notification via PHP:
require 'vendor/autoload.php';
$sns = Aws\Sns\SnsClient::factory(array(
'key' => 'mykey',
'secret' => 'mysecret',
'region' => 'us-east-1'
));
$snsmessage = $sns->publish(array(
'TargetArn' => "$endpoint",
'Message' => 'A game is waiting for you to play'
));
(where $endpoint = "arn:aws:sns:us-east-1:7860818154325:endpoint/APNS_SANDBOX/gamename/7412740a-79e4-3b71-8e7f-56e127bc4cg1")
$snsmessage returns a message ID, so it looks like it is sending the message.
However no message is ever received on the phone.
I have tried manually sending a message from the SNS portal and the same issue. IT sends with no error message but it never arrives.
I am building the app as "device testing" and I am using provisionprofile that has push notifcation enabled.
I am not sure where to start looking to find the issue.
Any help would be appreciated.

Categories