Send SMS using AWS SNS - .Net Core - amazon-web-services

I'm trying to use AWS world wide messaging service using C#/.Net Core.
However I do not receive the message in my phone number. Below is the code:
public static async Task<PublishResponse> sendSMS()
{
string accessKey = "my Key";
string secretAccessKey = "my secret key";
var client = new AmazonSimpleNotificationServiceClient(accessKey,
secretAccessKey, RegionEndpoint.USEast1);
string phoneNumber = "my number";
PublishRequest req = new PublishRequest();
req.Message = "Hellloooo from core";
req.PhoneNumber = "+2" + phoneNumber;
PublishResponse res = await client.PublishAsync(req);
return res;
}
And I invoke this method in the main function:
public static void Main(string[] args)
{
var respond = sendSMS();
}
I appreciate if anyone could help me with this. thanks in advance

public static async Task<PublishResponse> SendMessageToMobileAsync(string countryCode, string mobileNumber, string message)
{
var accessKey = "xxx";
var secretKey = "xxx";
var client = new AmazonSimpleNotificationServiceClient(accessKey, secretKey, RegionEndpoint.USEast1);
var messageAttributes = new Dictionary<string, MessageAttributeValue>();
var smsType = new MessageAttributeValue
{
DataType = "String",
StringValue = "Transactional"
};
messageAttributes.Add("AWS.SNS.SMS.SMSType", smsType);
PublishRequest request = new PublishRequest
{
Message = message,
PhoneNumber = countryCode + mobileNumber,
MessageAttributes = messageAttributes
};
return await client.PublishAsync(request);
}

the following function worked for me.
make sure that the account liked to credential you provided has SNS full access in AWS IAM Console
public static async Task SendSMS(AWSCredentials basicCred, string phoneNum, string message, string smsType= "Promotional")
{
AmazonSimpleNotificationServiceClient snsClient = new AmazonSimpleNotificationServiceClient(basicCred, Amazon.RegionEndpoint.APSoutheast2);
PublishRequest pubRequest = new PublishRequest();
pubRequest.Message = message;
// add optional MessageAttributes, for example:
pubRequest.MessageAttributes.Add("AWS.SNS.SMS.SenderID", new MessageAttributeValue
{ StringValue = "SSystems", DataType = "String" });
pubRequest.MessageAttributes.Add("AWS.SNS.SMS.MaxPrice", new MessageAttributeValue
{ StringValue = "0.50", DataType = "Number" });
pubRequest.PhoneNumber = phoneNum;
pubRequest.MessageAttributes.Add("AWS.SNS.SMS.SMSType", new MessageAttributeValue
{ StringValue = smsType, DataType = "String" });
PublishResponse pubResponse = await snsClient.PublishAsync(pubRequest);
Console.WriteLine(pubResponse.MessageId);
Console.ReadLine();
}

For new Comers
If you are using Aws toolkit for visual studio as I suppose
Nuget Packages:
AWSSDK.CORE
AWSSDK.Extensions.NETCore.Setup
AWSSDK.SimpleNotificationService
In your program.cs (.net core 6)
using Amazon.SimpleNotificationService;
and add your extensions
builder.Services.AddDefaultAWSOptions(builder.Configuration.GetAWSOptions());
builder.Services.AddAWSService<IAmazonSimpleNotificationService>(builder.Configuration.GetAWSOptions());
builder.Services.AddSingleton<ISMSSender, SMSSender>();
In appsettings
"AWS": {
"Profile": "aws toolkit profile name",
"Region": "aws region"
}
an ISMSSender interface for dependency injection:
public interface ISMSSender
{
Task<PublishResponse> SendSMSAsync(string phone, string subject, string Message);
}
Lastly your implementation:
public class SMSSender : ISMSSender
{
IAmazonSimpleNotificationService _SES;
public SMSSender(IAmazonSimpleNotificationService SES)
{
_SES = SES;
}
public Task<PublishResponse> SendSMSAsync(string phone, string subject, string Message)
{
var messageAttributes = new Dictionary<string, MessageAttributeValue>();
MessageAttributeValue senderID = new MessageAttributeValue();
senderID.DataType = "String";
senderID.StringValue = "sendername";
MessageAttributeValue sMSType = new MessageAttributeValue();
sMSType.DataType = "String";
sMSType.StringValue = "Transactional";//or Promotional according to AWS setup you choosed
MessageAttributeValue maxPrice = new MessageAttributeValue();
maxPrice.DataType = "Number";
maxPrice.StringValue = "0.5";
messageAttributes.Add("AWS.SNS.SMS.SenderID", senderID);
messageAttributes.Add("AWS.SNS.SMS.SMSType", sMSType);
messageAttributes.Add("AWS.SNS.SMS.MaxPrice", maxPrice);
var sendRequest = new PublishRequest()
{
Subject = subject,
Message = Message,
PhoneNumber =phone,
MessageAttributes = messageAttributes
};
try
{
Console.WriteLine("Sending SMS using AWS SES...");
var response = _SES.PublishAsync(sendRequest);
Console.WriteLine("The SMS was sent successfully.");
return response;
}
catch (Exception ex)
{
Console.WriteLine("The SMS was not sent.");
Console.WriteLine("Error message: " + ex.Message);
}
throw new NotImplementedException();
}
}
For usage use dependency injection into your Controller or class
private readonly ISMSSender _smsSender;
public MyController(ISMSSender smsSender)
{
_smsSender = smsSender;
}
and then Send Sms:
try
{
var result = await _smsSender.SendSMSAsync(
phoneNumber,
"Title",
"Message");
}
catch (Exception)
{
//handle failure
}
In order to send sms from your Ec2 or elastic Beanstalk app go to IAM roles and for role aws-elasticbeanstalk-ec2-role add permission AWSElasticBeanstalkRoleSNS and for role aws-elasticbeanstalk-service-role add permission AmazonSNSFullAccess

Related

Amazon Security Token Service for DigitalOcean

Is the AmazonSecurityTokenService available in DigitalOcean?
I have tried to generate a token but this is the error I get:
The service returned an error with Error Code MethodNotAllowed and
HTTP Body: MethodNotAllowedtx000000000000000135444-0063e479e5-28e12c76-sgp1b28e12c76-sgp1b-sgp1-zg02
Am I doing something wrong or is this function not available in DigitalOcean?
This is my function:
public static async Task<SessionAWSCredentials> GetTemporaryCredentials(string AccessKey, string AccessSecret, string Region)
{
try
{
var config = new AmazonSecurityTokenServiceConfig();
config.ServiceURL = $"{SDR_Core.ClassLibrary.Globals.StorageGlobals.HttpsProtocol}{Region}{SDR_Core.ClassLibrary.Globals.StorageGlobals.DO_Link}";
using (var stsClient = new AmazonSecurityTokenServiceClient(AccessKey, AccessSecret, config))
{
var getSessionTokenRequest = new GetSessionTokenRequest
{
DurationSeconds = 7200 // seconds
};
GetSessionTokenResponse sessionTokenResponse =
await stsClient.GetSessionTokenAsync(getSessionTokenRequest);
Credentials credentials = sessionTokenResponse.Credentials;
var sessionCredentials =
new SessionAWSCredentials(credentials.AccessKeyId,
credentials.SecretAccessKey,
credentials.SessionToken);
return sessionCredentials;
}
}
catch(Exception e)
{
if (e != null)
{
Console.WriteLine($"Temporary Credentials Exception: {e.Message}");
}
return null;
}
}

Use Aws4RequestSigner to sign PAAPI 5 Request

I'm trying to use Aws4RequestSigner in a VS2015 form to sign a search request to Amazon PAAPI.
https://www.nuget.org/packages/Aws4RequestSigner/
I get this response from the API:
{"__type":"com.amazon.paapi5#IncompleteSignatureException","Errors":[{"Code":"IncompleteSignature","Message":"The request signature did not include all of the required components. If you are using an AWS SDK, requests are signed for you automatically; otherwise, go to https://webservices.amazon.com/paapi5/documentation/sending-request.html#signing."}]}
private async void Form1_Load(object sender, EventArgs e)
{
_accessKey = "x";
_secretKey = "x";
_service = "ProductAdvertisingAPIv1";
_region = "us-east-1";
_requestUri = new Uri("https://webservices.amazon.com/paapi5/searchitems");
var payload = new
{
Keywords = "Harry",
Marketplace = "www.amazon.com",
PartnerTag = "x0d-20",
PartnerType = "Associates",
Resources = new string[] { "Images.Primary.Small", "ItemInfo.Title", "Offers.Listings.Price" },
SearchIndex = "All"
};
string jsonString = JsonConvert.SerializeObject(payload);
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
var xAmzDate = GetTimeStamp();
content.Headers.Add("content-encoding", "amz-1.0");
content.Headers.Add("x-amz-date", xAmzDate);
content.Headers.Add("x-amz-target", "com.amazon.paapi5.v1.ProductAdvertisingAPIv1.SearchItems");
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = _requestUri,
Content = content
};
request.Headers.Host = "webservices.amazon.com";
var contentType = new MediaTypeHeaderValue("application/json");
contentType.CharSet = "utf-8";
request.Content.Headers.ContentType = contentType;
var signer = new AWS4RequestSigner(_accessKey, _secretKey);
request = await signer.Sign(request, _service, _region);
try
{
var client = new HttpClient();
var response = await client.SendAsync(request);
if (!response.IsSuccessStatusCode)
{
var error = await response.Content.ReadAsStringAsync();
}
// response.EnsureSuccessStatusCode();
txtDisplay.Text = await response.Content.ReadAsStringAsync();
}
catch (HttpRequestException ex)
{
string error = ex.Message;
txtDisplay.Text = error;
}
}
private string GetTimeStamp()
{
return DateTime.UtcNow.ToString("yyyyMMdd\\THHmmss\\Z");
}
It could be that the headers are being added incorrectly or Aws4RequestSigner is simply outdated.

PowerBI Embedded: DeleteUserAsAdminAsync returns unauthorized

Receiving an unauthorized response when trying to remove a user from a workspace (group). I'm using the .Net SDK method DeleteUserAsAdminAsync. I tried the DeleteUserInGroupAsync method with the same result. I've had no trouble retrieving groups, reports, even adding users to groups using the same authentication code shown below. I'm quite stumped.
public async Task<ResultObject> RemoveUsersFromWorkspaces(List<PowerBIWorkspace> powerBIWorkspaces)
{
// Authenticate using created credentials
AuthenticationResult authenticationResult = null;
authenticationResult = await DoAuthentication("CustomerAppRegistration");
var tokenCredentials =
new TokenCredentials(authenticationResult.AccessToken, "Bearer");
using (var client = new PowerBIClient(
new Uri("https://api.powerbi.com/"), tokenCredentials))
{
try
{
foreach (var wksp in powerBIWorkspaces)
{
// Remove the user to the workspace.
await client.Groups.DeleteUserAsAdminAsync(new Guid(wksp.WorkspaceId), wksp.UserEmail);
}
}
catch (Exception ex)
{
var errorObject = new ResultObject();
errorObject.Success = false;
errorObject.ErrorMessage = ex.Message;
return errorObject;
}
}
var resultObject = new ResultObject();
resultObject.Success = true;
resultObject.ErrorMessage = "";
return resultObject;
}
private const string AuthorityFormat = "https://login.microsoftonline.com/{0}/v2.0";
private const string MSGraphScope = "https://analysis.windows.net/powerbi/api/.default";
private async Task<AuthenticationResult> DoAuthentication(string appRegistrationSection)
{
var config = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddJsonFile("appsettings.json").Build();
//var section = config.GetSection(nameof(AppRegistration));
var section = config.GetSection(appRegistrationSection);
var appRegistration = section.Get<AppRegistration>();
TenantID = appRegistration.TenantId;
ClientID = appRegistration.ClientId;
ClientSecret = appRegistration.ClientSecret;
IConfidentialClientApplication daemonClient;
daemonClient = ConfidentialClientApplicationBuilder.Create(ClientID)
.WithAuthority(string.Format(AuthorityFormat, TenantID))
.WithClientSecret(ClientSecret)
.Build();
AuthenticationResult authResult =
await daemonClient.AcquireTokenForClient(new[] { MSGraphScope }).ExecuteAsync();
return authResult;
}

how to send attached via email using SES and lambda in Java

I am trying to send the files stored in s3 via email using AWS SES and lambda in java. Mail has send successfully but when i am trying to open the file getting error "Excel cannot open the file 'filename.xlsx' because file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file."
Code Snippet in java :
public class EmailNotification {
static LambdaLogger logger = null;
private static String SENDER=null;
private static String RECIPIENT=null;
private static String SUBJECT=null;
private static String BODY_TEXT=null;
private static String filekey=null;
public void verifyEmailNotification(Context context) throws Exception {
LambdaLogger logger = null;
try {
logger = context.getLogger();
String bucket_name = "bucket_name";
String key_name = "path/";
String file_name ="file_name.xlsx";
filekey = key_name + file_name;
AmazonS3 s3client = GetAWSClients.getS3();
boolean isFileExists=Utility.checkIfFileExists(bucket_name, filekey);
logger.log("isFileExists " + isFileExists);
if (isFileExists)
filekey = key_name + file_name;
else
logger.log("file not available");
InputStream stream = s3client.getObject(bucket_name, filekey).getObjectContent();
XSSFWorkbook workbook = new XSSFWorkbook(stream);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
workbook.write(bos);
ByteArrayInputStream contentsAsStream = new ByteArrayInputStream(bos.toByteArray());
ObjectMetadata md = new ObjectMetadata();
md.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
md.setSSEAlgorithm(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION);
md.setContentLength(bos.toByteArray().length);
SENDER = "sender email";
RECIPIENT = "receiver email";
SUBJECT = "subject";
BODY_TEXT = "Body text";
Session session = Session.getDefaultInstance(new Properties());
MimeMessage message = new MimeMessage(session);
message.setSubject(SUBJECT);
message.setFrom(new InternetAddress(SENDER));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(RECIPIENT));
MimeMultipart msg_body = new MimeMultipart("alternative");
MimeBodyPart textPart = new MimeBodyPart();
textPart.setContent(BODY_TEXT, "text/plain; charset=UTF-8");
msg_body.addBodyPart(textPart);
MimeBodyPart att = new MimeBodyPart();
DataSource fds = new ByteArrayDataSource(bos.toByteArray(), "application/octet-stream");
att.setDataHandler(new DataHandler(fds));
att.setFileName(TemplateFile);
message.setContent(msg_body);
msg_body.addBodyPart(att);
try {
System.out.println("Attempting to send an email through Amazon SES "
+"using the AWS SDK for Java...");
AmazonSimpleEmailService client = GetAWSClients.getSES();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
message.writeTo(outputStream);
RawMessage rawMessage = new RawMessage(ByteBuffer.wrap(outputStream.toByteArray()));
SendRawEmailRequest rawEmailRequest = new SendRawEmailRequest(rawMessage);
client.sendRawEmail(rawEmailRequest);
System.out.println("Email sent!");
workbook.close();
} catch (Exception ex) {
System.out.println("Email Failed");
System.err.println("Error message: " + ex.getMessage());
ex.printStackTrace();
}
}
catch(Exception ex) {
System.out.println("Email Failed");
System.err.println("Error message: " + ex.getMessage());
ex.printStackTrace();
}
}
}
Used POI and workbooks concept and resolved the issue.
public void verifyEmailNotification(Context context) throws IOException, MessagingException {
String bucketName = "bucketName";
String key = "prefix";
String fileName = "fileName.xlsx";
String keyName = key + fileName;
S3Object fullObject = null;
try {
SENDER = "sender email";
RECIPIENT = "receiver email";
SUBJECT = "Subject msg";
BODY_TEXT = "Hi";
logger = context.getLogger();
AmazonS3Client s3Client = (AmazonS3Client) AmazonS3ClientBuilder.defaultClient();
InputStream stream = s3Client.getObject(new GetObjectRequest(bucketName, keyName)).getObjectContent();
// Preparing input-stream as spreed sheet.
XSSFWorkbook workbook = new XSSFWorkbook(stream);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
workbook.write(bos);
logger.log("Read success\n");
Session session = Session.getDefaultInstance(new Properties());
MimeMessage message = new MimeMessage(session);
message.setSubject(SUBJECT);
message.setFrom(new InternetAddress(SENDER));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(RECIPIENT));
MimeMultipart msg_body = new MimeMultipart("alternative");
MimeBodyPart textPart = new MimeBodyPart();
textPart.setContent(BODY_TEXT, "text/plain; charset=UTF-8");
msg_body.addBodyPart(textPart);
// Preparing the attachment from the spread sheet
MimeBodyPart att = new MimeBodyPart();
DataSource fds = new ByteArrayDataSource(bos.toByteArray(), "application/octet-stream");
att.setDataHandler(new DataHandler(fds));
att.setFileName(fileName);
msg_body.addBodyPart(att);
message.setContent(msg_body);
logger.log("attachment prepared\n");
AmazonSimpleEmailServiceClientBuilder.standard().withRegion(Regions.US_EAST_1).build();
AmazonSimpleEmailService client = GetAWSClients.getSES();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
message.writeTo(outputStream);
RawMessage rawMessage = new RawMessage(ByteBuffer.wrap(outputStream.toByteArray()));
SendRawEmailRequest rawEmailRequest = new SendRawEmailRequest(rawMessage);
client.sendRawEmail(rawEmailRequest);
System.out.println("Email sent!");
} catch (AmazonServiceException e) {
// The call was transmitted successfully, but Amazon S3 couldn't process
// it, so it returned an error response.
e.printStackTrace();
} catch (SdkClientException e) {
// Amazon S3 couldn't be contacted for a response, or the client
// couldn't parse the response from Amazon S3.
e.printStackTrace();
}
}

Pass field from Droid project to PCL, Xamarin.Forms

I have an app that allows users to log in via facebook, once user enters their credentials - My api request saves the user onto the database and auto-generates a user token(This is unique to each user). In order to display user specific details once user logs in - the token needs to be referenced. I am trying to get this token to the PCL project but it returns null just for the token. When I tried passing another string like name, it passes the correct value. Any help will be much appreciated.Thanks
FacebookRender in droid:
public class FacebookRender : PageRenderer
{
public FacebookRender()
{
CustomerService customerService = new CustomerService();
String error;
var activity = this.Context as Activity;
var auth = new OAuth2Authenticator(
clientId: "",
scope: "",
authorizeUrl: new Uri("https://www.facebook.com/dialog/oauth/"),
redirectUrl: new Uri("https://www.facebook.com/connect/login_success.html")
);
auth.Completed += async (sender, eventArgs) =>
{
try
{
if (eventArgs.IsAuthenticated)
{
await AccountStore.Create().SaveAsync(eventArgs.Account, "FacebookProviderKey");
var accessToken = eventArgs.Account.Properties["access_token"].ToString();
var expiresIn = Convert.ToDouble(eventArgs.Account.Properties["expires_in"]);
var expiryDate = DateTime.Now + TimeSpan.FromSeconds(expiresIn);
var request = new OAuth2Request("GET", new Uri("https://graph.facebook.com/me?fields=email,first_name,last_name,gender,picture"), null, eventArgs.Account);
var response = await request.GetResponseAsync();
var obj = JObject.Parse(response.GetResponseText());
var id = obj["id"].ToString().Replace("\"", "");
var name = obj["first_name"].ToString().Replace("\"", "");
var surname = obj["last_name"].ToString().Replace("\"", "");
var gender = obj["gender"].ToString().Replace("\"", "");
//var email = obj["email"].ToString().Replace("\"", "");
Customer.Customers cust = new Customer.Customers();
cust.Credentials = new Customer.Credentials();
cust.Name = name;
cust.Surname = surname;
cust.Email = "";
cust.MobilePhone = "";
cust.DOB = DateTime.Now;
cust.Number = "";
cust.City = "";
cust.Region = "";
cust.Country = "";
cust.DeviceToken = "sample";
cust.Credentials.SecretKey = "";
await customerService.AddCustomer(cust);
App.SaveToken(cust.Credentials.Token); - **//This is where I am passing the token**
App.NavigateToProfile(string.Format(name + surname));
}
else
{
App.NavigateToProfile("Invalid Login");
}
}
catch(Exception ex)
{
error = ex.Message;
}
};
activity.StartActivity(auth.GetUI(activity));
}
App.cs
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
}
public static void NavigateToProfile(string message)
{
App.Current.MainPage = (new Profile(message));
}
static string _Token;
public static string Token
{
get { return _Token; }
}
public static void SaveToken(string token)
{
_Token = token;
}
AboutPage.cs - I am passing the token in a label just to see if it's passing
public partial class About : ContentPage
{
private Label _lbltoken;
public About()
{
//InitializeComponent();
Appearing += (object s, EventArgs a) => {
_lbltoken.Text = App.Token;
};
string tk = App.Token;
_lbltoken = new Label()
{
FontSize = 20,
HorizontalOptions = LayoutOptions.CenterAndExpand,
Text = tk,
};
var stack = new StackLayout
{
VerticalOptions = LayoutOptions.StartAndExpand,
Children = { _lbltoken },
};
Content = stack;
}
}
You can use the MessagingCenter.
Messages may be sent as a result like a button click, a system event or some other incident. Subscribers might be listening in order to change the appearance of the user interface, save data or trigger some other operation.
More Info
I don't really now if its good idea use static fields in App class. Xamarin access all fields with service locator, App.Current.[property] I will suggest you try to change these fields to public
string _Token;
public string Token
{
get { return _Token; }
}
public void SaveToken(string token)
{
_Token = token;
}
and use it with App.Current.SaveToken(token) or App.Current.Token