AWS SNS: Not sending sms to phone number - amazon-web-services

I am trying a small demo for sending SMS to numbers here in India. I used following code snippet but not working.
public void send(String to, String textBody) {
AWSCredentials awsCredentials;
awsCredentials = new EnvironmentVariableCredentialsProvider().getCredentials();
AmazonSNSClient snsClient = new AmazonSNSClient(awsCredentials);
PublishResult result = snsClient
.publish(new PublishRequest().withMessage(textBody)
.withPhoneNumber("+9195355*****"));
System.out.println(result);
}
I am not able to figure out what is missing?

Since you've confirmed that sending SMS using the SNS console,the messages are delivered successfully then this seems to suggest that there could be an issue with the provided code snippet!
I've modified your code snippet slightly and I've confirmed the following code snippet to be working without issues :
public static void main(String[] args) {
ProfileCredentialsProvider creds = new ProfileCredentialsProvider("syumaK");
AmazonSNS snsClient = AmazonSNSClientBuilder.standard().withCredentials(creds).withRegion("us-east-1").build();
String textBody = "My test SMS message from SNS";
String to = "+0123456789";
send(snsClient, to, textBody);
}
public static void send(AmazonSNS snsClient, String to, String textBody) {
try {
PublishResult result = snsClient
.publish(new PublishRequest()
.withMessage(textBody)
.withPhoneNumber(to));
System.out.println(result);
LOGGER.info("Message send with id {}."+ result.getMessageId());
} catch (AmazonSNSException e) {
LOGGER.info("Got an exception. " + e.getMessage())
}
}
Troubleshooting Steps:
-If using ProfileCredentialsProvider works just like above, consider switching back to EnvironmentVariableCredentialsProvider or using BasicAWSCredentials provider and check if you observe any success/failure?
I have tested the above code snippet using the following environment spec:
OS : Ubuntu 16.04
aws region: us-east-1
aws-java-sdk: "1.11.723"

Related

S3Exception: The bucket you are attempting to access must be addressed using the specified endpoint

I know that there are many similar questions, and this one is no exception
But unfortunately I can't decide on the region for my case, how can I decide on the right region?
For example, when making a request to Postman, I encounter a similar error:
In my console i'm using EU (Frankfurt) eu-central-1 and also in terminal write smth like this:
heroku config:set region="eu-central-1"
And as I understand it, mine does not fit.
Also here is my AWS class:
class AmazonFileStorage : FileStorage {
private val client: S3Client
private val bucketName: String = System.getenv("bucketName")
init {
val region = System.getenv("region")
val accessKey = System.getenv("accessKey")
val secretKey = System.getenv("secretKey")
val credentials = AwsBasicCredentials.create(accessKey, secretKey)
val awsRegion = Region.of(region)
client = S3Client.builder()
.credentialsProvider(StaticCredentialsProvider.create(credentials))
.region(awsRegion)
.build() as S3Client
}
override suspend fun save(file: File): String =
withContext(Dispatchers.IO) {
client.putObject(
PutObjectRequest.builder().bucket(bucketName).key(file.name).acl(ObjectCannedACL.PUBLIC_READ).build(),
RequestBody.fromFile(file)
)
val request = GetUrlRequest.builder().bucket(bucketName).key(file.name).build()
client.utilities().getUrl(request).toExternalForm()
}
}
I think you may have the wrong region code; you do know that a Bucket is available in one and only one Region?
In your logging settings, set this scope to debug:
logging:
level:
org.apache.http.wire: debug
Then you should see something like this:
http-outgoing-0 >> "HEAD /somefile HTTP/1.1[\r][\n]"
http-outgoing-0 >> "Host: YOURBUCKETNAME.s3.eu-west-2.amazonaws.com[\r][\n]"
That log is from a bucket in the London region eu-west-2
To use Kotlin to interact with an Amazon S3 bucket (or other AWS services), consider using the AWS SDK for Kotlin. This SDK is meant for Kotlin developers. You are using the AWS SDK for Java.
To put an object into an Amazon S3 bucket using the AWS SDK for Kotlin, use this code. Notice the region that you want to use is specified in the code block where you define the aws.sdk.kotlin.services.s3.S3Client.
import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.model.PutObjectRequest
import aws.smithy.kotlin.runtime.content.asByteStream
import java.io.File
import kotlin.system.exitProcess
/**
Before running this Kotlin code example, set up your development environment,
including your credentials.
For more information, see the following documentation topic:
https://docs.aws.amazon.com/sdk-for-kotlin/latest/developer-guide/setup.html
*/
suspend fun main(args: Array<String>) {
val usage = """
Usage:
<bucketName> <objectKey> <objectPath>
Where:
bucketName - The Amazon S3 bucket to upload an object into.
objectKey - The object to upload (for example, book.pdf).
objectPath - The path where the file is located (for example, C:/AWS/book2.pdf).
"""
if (args.size != 3) {
println(usage)
exitProcess(0)
}
val bucketName = args[0]
val objectKey = args[1]
val objectPath = args[2]
putS3Object(bucketName, objectKey, objectPath)
}
suspend fun putS3Object(bucketName: String, objectKey: String, objectPath: String) {
val metadataVal = mutableMapOf<String, String>()
metadataVal["myVal"] = "test"
val request = PutObjectRequest {
bucket = bucketName
key = objectKey
metadata = metadataVal
body = File(objectPath).asByteStream()
}
S3Client { region = "us-east-1" }.use { s3 ->
val response = s3.putObject(request)
println("Tag information is ${response.eTag}")
}
}
You can find this Kotlin example and many more in the AWS Code Library here:
Amazon S3 examples using SDK for Kotlin
ALso you can read the Kotlin DEV guide too. The link is at the start of the Code Example.

Springboot Communication with S3 bucket

i have got a problem i can't resolve for some hours, so i decide to post it with the hope someone can help me there.
So basically i'm trying to connect my springboot to an s3 bucket i created on the AWS console manager and store some images i supply.
Here is my code java :
#Service
public class AmazonClient {
private AmazonS3 s3client;
#Value("${amazonProperties.endpointUrl}")
private String endpointUrl;
#Value("${amazonProperties.bucketName}")
private String bucketName;
#Value("${amazonProperties.accessKey}")
private String accessKey;
#Value("${amazonProperties.secretKey}")
private String secretKey;
#Value("${amazonProperties.region}")
private String region;
#PostConstruct
private void initializeAmazon() {
System.out.println(this.accessKey+'\n'+this.secretKey+'\n'+Regions.fromName(this.region));
BasicAWSCredentials credentials = new BasicAWSCredentials(this.accessKey, this.secretKey);
AmazonS3 amazonS3Client = AmazonS3ClientBuilder.standard()
.withRegion(Regions.fromName(region))
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.build();
this.s3client = amazonS3Client;
System.out.println(this.s3client);
}
private void uploadFileTos3bucket(String fileName, File file) {
s3client.putObject(new PutObjectRequest(bucketName, fileName, file)
.withCannedAcl(CannedAccessControlList.PublicRead));
}
public String uploadFile(MultipartFile multipartFile) {
String fileUrl = "";
try {
File file = convertMultiPartToFile(multipartFile);
String fileName = generateFileName(multipartFile);
fileUrl = endpointUrl + "/" + bucketName + "/" + fileName;
uploadFileTos3bucket(fileName, file);
file.delete();
} catch (Exception e) {
e.printStackTrace();
}
return fileUrl;
}
}
Getting com.amazonaws.services.s3.model.AmazonS3Exception: The AWS Access Key Id you provided does not exist in our records. (Service: Amazon S3; Status Code: 403; Error Code: InvalidAccessKeyId; Request ID: TDH3Q44GGPGGY2DD; S3 Extended Request ID: oQOOA9bu3bhoHNudJEOFkto1aXEjxKVfblnFWAJ2eJmFTG6mnKSHycHeQpbLP4kYITG9pQxNx9o=; Proxy: null), S3 Extended Request ID: oQOOA9bu3bhoHNudJEOFkto1aXEjxKVfblnFWAJ2eJmFTG6mnKSHycHeQpbLP4kYITG9pQxNx9o=
error when i call the upload method throught postman post request intercepted by controler...
The thing is i can't create an IAM user because i got a restricted AWS free 100$ account given by my school to work on. The permissions S3fullaccess is given to a predifined role assigned to current user. Consequently, aws CLI command aws s3 ls well list the bucket with accurate credential configuration. However, cant put any object in the bucket ....
I'm driving crazy because it seems like everything is working on the springboot part : the println(accesskey, secretkey and region are well fetched from my application.yml following:
amazonProperties:
endpointUrl: https://s3.amazonaws.com
accessKey: XXXXXX
secretKey: XXXXXX
bucketName: image-bucket-cpe
region: us-east-1
).
If someone can help me, i will be forever beholden to him.
Thanks in advance

java.lang.ClassNotFoundException on ClasspathPropertiesFileCredentialsProvider in a Kotlin project for Windows

I created a console application for Windows in Kotlin.
In that app, I want to send files to an AWS S3 bucket.
For that purpose, I initiate my S3 client like the following:
// credentials provider :
val classpathPropertiesFileCredentialsProvider = ClasspathPropertiesFileCredentialsProvider("AWSCredentials.properties")
// S3 client :
val amazonS3: AmazonS3 = AmazonS3ClientBuilder.standard()
.withRegion("eu-central-1")
.withCredentials(classpathPropertiesFileCredentialsProvider)
.build()
And here are all the imports in my build.gradle file:
implementation 'com.amazonaws:aws-java-sdk-opensdk:1.12.58'
implementation 'com.amazonaws:aws-java-sdk-core:1.12.58'
implementation 'com.amazonaws:aws-java-sdk-apigatewayv2:1.12.58'
implementation 'com.amazonaws:aws-java-sdk-cognitoidentity:1.12.58'
implementation 'com.amazonaws:aws-java-sdk-cognitoidp:1.12.58'
implementation 'com.amazonaws:aws-java-sdk-s3:1.12.58'
implementation 'com.amazonaws:aws-java-sdk-sts:1.12.58'
implementation 'com.amazonaws:aws-java-sdk-s3control:1.12.58'
The project compiles without any error, but when I run it, I get the following error:
java.lang.ClassNotFoundException: com.amazonaws.auth.ClasspathPropertiesFileCredentialsProvider
which I don't understand, since I did the same in another Java Swing project, and it works fine.
Did I miss something?
Thanks.
To work with Kotlin and AWS Services such as Amazon S3, you should consider using the AWS SDK for Kotlin. This is a newer SDK built for Kotlin developers. You are currently using the AWS SDK for Java V1. If you are using Java, then you should move from V1 to Java V2.
To learn how to get started with the AWS SDK for Kotlin, see this topic:
https://github.com/awslabs/aws-sdk-kotlin/blob/main/docs/GettingStarted.md
To work with Amazon S3 and Kotlin, refer to the code examples in Github here.
To upload a file to an Amazon S3 bucket using the Kotlin SDK, use this code:
package com.kotlin.s3
// snippet-start:[s3.kotlin.s3_object_upload.import]
import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.model.PutObjectRequest
import aws.sdk.kotlin.services.s3.model.S3Exception
import aws.smithy.kotlin.runtime.content.ByteStream
import java.io.File
import java.io.FileInputStream
import java.io.IOException
import kotlin.system.exitProcess
// snippet-end:[s3.kotlin.s3_object_upload.import]
/**
To run this Kotlin code example, ensure that you have setup your development environment,
including your credentials.
For information, see this documentation topic:
https://docs.aws.amazon.com/sdk-for-kotlin/latest/developer-guide/setup.html
*/
suspend fun main(args: Array<String>) {
val usage = """
Usage:
<bucketName> <objectKey> <objectPath>
Where:
bucketName - the Amazon S3 bucket to upload an object into.
objectKey - the object to upload (for example, book.pdf).
objectPath - the path where the file is located (for example, C:/AWS/book2.pdf).
"""
if (args.size != 3) {
println(usage)
exitProcess(0)
}
val bucketName = args[0]
val objectKey = args[1]
val objectPath = args[2]
val s3Client = S3Client { region = "us-east-1" }
putS3Object(s3Client, bucketName, objectKey, objectPath)
s3Client.close()
}
// snippet-start:[s3.kotlin.s3_object_upload.main]
suspend fun putS3Object(
s3Client: S3Client,
bucketName: String,
objectKey: String,
objectPath: String
){
try {
val metadataVal = mutableMapOf<String, String>()
metadataVal["myVal"] = "test"
val putOb = PutObjectRequest {
bucket = bucketName
key = objectKey
metadata = metadataVal
this.body = ByteStream.fromBytes(getObjectFile(objectPath))
}
val response =s3Client.putObject(putOb)
println("Tag information is ${response.eTag}")
} catch (e: S3Exception) {
println(e.message)
s3Client.close()
exitProcess(0)
}
}
fun getObjectFile(filePath: String): ByteArray {
var fileInputStream: FileInputStream? = null
lateinit var bytesArray: ByteArray
try {
val file = File(filePath)
bytesArray = ByteArray(file.length().toInt())
fileInputStream = FileInputStream(file)
fileInputStream.read(bytesArray)
} catch (e: IOException) {
println(e.message)
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close()
} catch (e: IOException) {
println(e.message)
}
}
}
return bytesArray
}
NOTE that all examples assume that your creds are located in a file named credentials as explained here:
Setting the default credentials

How to prepare Pub/Sub emulator for tests?

I start the gcloud sdk docker
docker run -ti --rm --expose=8085 -p 8085:8085 google/cloud-sdk:latest
then i run:
gcloud beta emulators pubsub start --project=my-project --host-port=0.0.0.0:8085
then stop the sever and then:
gcloud beta emulators pubsub env-init
gives:
export PUBSUB_EMULATOR_HOST=0.0.0.0:8085
but there is no project id. How can I setup project for tests? How can i create topics and subscriptions?
version:
gcloud version
gives:
Google Cloud SDK 236.0.0
...
pubsub-emulator 2019.02.22
You are launching pubsub emulator with project my-project in your 2nd command. Once this is running, don't kill it, leave it running.
To create the topics and subscriptions, you have to use one of the SDKs. I created a demo project that does this using the Java SDK: https://github.com/nhartner/pubsub-emulator-demo/
The relevant code is this:
#Component
public class TestPubSubConfig {
private final TransportChannelProvider channelProvider;
private final CredentialsProvider credentialsProvider;
private String projectId;
private String topicName = "test-topic";
private String subscriptionName = "test-subscription";
TestPubSubConfig(#Autowired #Value("${spring.cloud.gcp.pubsub.emulator-host}") String emulatorHost,
#Autowired #Value("${spring.cloud.gcp.project-id}") String projectId) throws IOException {
this.projectId = projectId;
ManagedChannel channel = ManagedChannelBuilder.forTarget(emulatorHost).usePlaintext().build();
channelProvider = FixedTransportChannelProvider.create(GrpcTransportChannel.create(channel));
credentialsProvider = NoCredentialsProvider.create();
createTopic(topicName);
createSubscription(topicName, subscriptionName);
}
#Bean
public Publisher testPublisher() throws IOException {
return Publisher.newBuilder(ProjectTopicName.of(projectId, topicName))
.setChannelProvider(channelProvider)
.setCredentialsProvider(credentialsProvider)
.build();
}
private void createSubscription(String topicName, String subscriptionName) throws IOException {
ProjectTopicName topic = ProjectTopicName.of(projectId, topicName);
ProjectSubscriptionName subscription = ProjectSubscriptionName.of(projectId, subscriptionName);
try {
subscriptionAdminClient()
.createSubscription(subscription, topic, PushConfig.getDefaultInstance(), 100);
}
catch (AlreadyExistsException e) {
// this is fine, already created
}
}
private void createTopic(String topicName) throws IOException {
ProjectTopicName topic = ProjectTopicName.of(projectId, topicName);
try {
topicAdminClient().createTopic(topic);
}
catch (AlreadyExistsException e) {
// this is fine, already created
}
}
private TopicAdminClient topicAdminClient() throws IOException {
return TopicAdminClient.create(
TopicAdminSettings.newBuilder()
.setTransportChannelProvider(channelProvider)
.setCredentialsProvider(credentialsProvider).build());
}
private SubscriptionAdminClient subscriptionAdminClient() throws IOException {
return SubscriptionAdminClient.create(SubscriptionAdminSettings.newBuilder()
.setTransportChannelProvider(channelProvider)
.setCredentialsProvider(credentialsProvider)
.build());
}
}
A possible gotchya we uncovered while working with the Pub/Sub emulator is that the documentation says:
In this case, the project ID can be any valid string; it does not
need to represent a real GCP project because the Cloud Pub/Sub
emulator runs locally.
any valid string in this context is not any string, but specifically a valid one, meaning it looks like a valid GC Project Id. In our testing this was specifically strings that match the REGEX pattern:
/^[a-z]-[a-z]-\d{6}$/
Once supplied with a valid project ID, the emulator works as advertised. If you have a sandbox project in GC you can use that ID or you can make up your own that matches that pattern. Once you got that far you can follow the remainder of the Testing apps locally with the emulator documentation.

Grails AWS SDK plugin not resolving PutObjectRequest

I am trying to get my grails app working with Amazon S3, I have been following the following docs... http://agorapulse.github.io/grails-aws-sdk/guide/single.html
At the following step amazonWebService.s3.putObject(new PutObjectRequest('some-grails-bucket', 'somePath/someKey.jpg', new File('/Users/ben/Desktop/photo.jpg')).withCannedAcl(CannedAccessControlList.PublicRead))
The project can't resolve class PutObjectRequest, and I have tried importing com.amazonaws.services.s3.model.PutObjectRequest manually, but it still cant find the class. The only thing I can think of is I might have an older version of the SDK, though I only followed the tutorial.
My BuildConfig.groovy...
...
dependencies{
//dependencies for amazon aws plugin
build 'org.apache.httpcomponents:httpcore:4.3.2'
build 'org.apache.httpcomponents:httpclient:4.3.2'
runtime 'org.apache.httpcomponents:httpcore:4.3.2'
runtime 'org.apache.httpcomponents:httpclient:4.3.2'
}
plugins{
...
runtime ':aws-sdk:1.9.40'
}
has anyone else run into this issue and have a solution?
I don't use the plugin, I simply just use the SDK directly. Not sure what you would need a plugin for. You don't need httpcomponents for it to work
Add this to you dependencies block:
compile('com.amazonaws:aws-java-sdk-s3:1.10.2') {
exclude group: 'com.fasterxml.jackson.core'
}
Heres my bean I use. I set the key, access, and bucket data in the bean configuration
class AmazonStorageService implements FileStorageService {
String accessKeyId
String secretAccessKey
String bucketName
AmazonS3Client s3client
#PostConstruct
private void init() {
s3client = new AmazonS3Client(new BasicAWSCredentials(accessKeyId, secretAccessKey));
}
String upload(String name, InputStream inputStream) {
s3client.putObject(new PutObjectRequest(bucketName, name, inputStream, null).withCannedAcl(CannedAccessControlList.PublicRead));
getUrl(name)
}
String upload(String name, byte[] data) {
upload(name, new ByteArrayInputStream(data))
}
String getUrl(String name) {
s3client.getUrl(bucketName, name)
}
Boolean exists(String name) {
try {
s3client.getObjectMetadata(bucketName, name)
true
} catch(AmazonServiceException e) {
false
}
}
}