Creating AWS SES SMTP credentials using IAM Role - python

I am trying to use an IAM Role that I have attached to an EC2 instance to generate a set of AWS SES SMTP credentials. However, after using the script given by Amazon to generate the SMTP Password from the Secret_Key of the IAM Role, and using the Access_Key_ID of the IAM Role, when trying to send an email via django.core.mail, I get error (535, b'Authentication Credentials Invalid').
This is how I am sending the email:
#django.core.mail
EMAIL_USE_TLS = True
EMAIL_HOST = 'email-smtp.us-east-1.amazonaws.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = credentials.access_key
EMAIL_HOST_PASSWORD = SMTP_PASSWORD
send_mail(
'Subject here',
'Here is the message.',
'from#example.com',
['to#example.com'],
fail_silently=False,
)
And how am I generating the password:
session = boto3.session.Session()
credentials = session.get_credentials().get_frozen_credentials()
region = requests.get('http://169.254.169.254/latest/dynamic/instance-identity/document').json()['region']
SMTP_PASSWORD = smtp_credentials_generate.calculate_key(secret_access_key=credentials.secret_key, region=region)
The SMTP Password generate script is here: https://docs.aws.amazon.com/ses/latest/DeveloperGuide/smtp-credentials.html.
Through some research, I found these links that say you cannot use an IAM Role to use generate SMTP credentials:
https://serverfault.com/questions/584789/is-it-possible-to-send-email-via-the-amazon-ses-smtp-service-with-a-iam-role-acc
https://hector.dev/2015/01/17/sending-e-mail-via-amazon-ses-over-smtp-with-iam-roles.html
However, Amazons official QA says that it is possible:
https://aws.amazon.com/premiumsupport/knowledge-center/ses-create-smtp-credentials/
Important: The IAM user or role that you use to create the SMTP credentials...
So is it possible or not? What am I doing wrong?

https://docs.aws.amazon.com/ses/latest/DeveloperGuide/smtp-credentials.html
Don't use temporary AWS credentials to derive SMTP credentials. The Amazon SES SMTP interface doesn't support SMTP credentials that have been generated from temporary security credentials.
Regarding the Amazon official QA that you referenced, it's saying that you can use the role to create SMTP credentials in the web console.

Related

Publish SMS messages through master account in AWS

We have a multi-account setup on AWS. There is a master account and separated accounts for dev, staging and prod. We have enabled sending SMS messages on the master account (exited the SMS sandbox).
I would like now to send sms message through the master account from the dev one. In a standard case, I would just publish a message to the correct ARN (and make sure earlier that proper permissions exist). However, while sending SMS messages, there is no ARN, so I am stuck. Is there a way to achieve it?
For the reference, this is how I can send a message on dev (with the sandbox mode on):
client = boto3.client("sns")
try:
client.publish(
PhoneNumber=recipient,
Message=message,
MessageAttributes={
'AWS.SNS.SMS.SenderID': {
'DataType': 'String',
'StringValue': sender
}
}
)
except botocore.exceptions.ClientError as error: # noqa
logger.error(f'An error occurred while sending SMS message: {error}')
Is there a way to target different account? I was thinking about providing a aws_access_key_id and aws_secret_access_key but maybe there is another way?
You should:
Create an IAM Role in the master account that has permissions to send the SMS message, and a trust policy that allows the IAM Role to be 'assumed' from the child account
Grant permission to the appropriate IAM User or IAM Role in the child account to assume the IAM Role in the master account
The code would then call AssumeRole() to assume the IAM Role from the master account and then use the returned credentials to send the SMS message

Why I am getting b' authentication failed error even if my username password are correct?

Everytime, I am trying to login into my Gmail account using python script it always shows authentication failed . I have used the right username and password, My internet connection is stable and I have turned on the 'less secure app access' from gmail setting.
from imap_tools import MailBox
with MailBox('imap.mail.com').login('sample#gmail.com', 'exm123') as mailbox:
subjects = [msg.subject for msg in mailbox.fetch()]
mailbox = MailBox('imap.gmail.com')
mailbox.login('sample#gmail.com', 'exm123', initial_folder='INBOX') # or mailbox.folder.set instead 3d arg
subjects = [msg.subject for msg in mailbox.fetch(AND(all=True))]
mailbox.logout()

Connect to microsoft graph API

I have created an azure application using the Microsoft azure platform.
using the below script I make an attempt to connect to the API using the credentials given when creating the azure application.
from O365 import Account
credentials = ('azureApp_clientId', 'azureApp_clientSecret')
account = Account(credentials)
if account.authenticate(scopes=['Mail.Read']):
print('Authenticated!')
When the script runs it returns a URL to add to a browser and give consent..
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?xxxxxxxxxx
When i paste the URL into my browser it does nothing and returns a blank page..
This is my redirect URI in the azure app
What am I missing??
Docs to o365 Lib here https://pypi.org/project/O365/
Update
from O365 import Account
credentials = ('myclientID')
account = Account(credentials, auth_flow_type = 'public')
if account.authenticate(scopes = ['Mail.Read']):
print('Authenticated!')
mailbox = account.mailbox()
inbox = mailbox.inbox_folder()
for message in inbox.get_messages():
print(message)
Update
According to the configuration of the application azure (you register the application as Mobile and desktop applications), you should use the method Authenticate on behalf of a user (public) to do auth and should not provide client_secret. For more details, please refer to here and here.
For example
from O365 import Account
credentials = ('<your client_id>',)
account = Account(credentials,auth_flow_type='public')
if account.authenticate(scopes==['Mail.Read'] ):
print('Authenticated!')
mailbox = account.mailbox()
inbox = mailbox.inbox_folder()
for message in inbox.get_messages():
print(message)
#Update
My configuration

Sending mail python webapp2 GAE

I initially tried using the smptlib library but in order to send an e-mail I need to use SSL which costs me with Google App Engine. Other than that, smtplib was a perfect solution.
I found a link here which explains how to send an email using the GAE API.
However, I can't seem to figure out how one would log in to a gmail account say, in order to send the email.
The purpose of this is to send a verification email to addresses of those who are registering. But in the link it shows how to get the current_user and send the email using their credentials. How would I explicitly enter an email, password, and smtp server like I would do with smtplib in order to send the email from my desired address.
Thanks for any answers!
You can't send from an arbitrary email address. As the overview docs state, you can only send from:
The Gmail or Google Apps Account of the user who is currently signed in
Any email address of the form anything#appname.appspotmail.com or anything#appalias.appspotmail.com
Any email address listed in Email API Authorized Senders found in the App Engine Settings page of the Developers Console
If you are the owner of the email account you want to send from, and it is a GMail account, you can add it to the Email API Authorized Senders list from the App Engine console.
Once that's done, you can just use it as the sender address - you don't need to log into anything.

Django & Amazon SES SMTP. Cannot send email

this is my settings.py :
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'email-smtp.us-east-1.amazonaws.com'
EMAIL_PORT = '465'
EMAIL_HOST_USER = config_data['EMAIL_HOST_USER']
EMAIL_HOST_PASSWORD = config_data['EMAIL_HOST_PASSWORD']
EMAIL_USE_SSL = True
I have verified the email addresses and have also generated SMTP credentials which I downloaded the credentials containing the IAM username, Smtp username, Smtp password. I used the smtp username for EMAIL_HOST_USER and smtp password for EMAIL_HOST_PASSWORD.
In django, I sent an email with this line (admin#admin.com is replaced with a gmail account that is in the verified email list) :
send_mail("Subject", "content", "admin#admin.com", [email], fail_silently=False)
That did not work. Sending a test email from the SES console (select one of the email in verified emails and click send a test email button) works though.
This document says that I can send email via command line with openssl command. So, i did ssh to the EC2 machine, and use :
openssl s_client -crlf -quiet -starttls smtp -connect email-smtp.us-east-1.amazonaws.com:25
Notice that i used 25 here, when i used port 465, it outputed :
didn't found starttls in server response, try anyway...
write:errno=32
So instead I tried port 25, It connected (250 OK) and then I typed :
AUTH LOGIN
334 VXNlcm5hbWU6
SMTP_USER
334 UGFzc3dvcmQ6
SMTP_PASSWORD
but it outputted : 535 Authentication Credentials Invalid. Could it be I used a wrong credentials? but I copy the username and password straight from the smtp user and password generation page.
I also tried to attach AmazonSESFullAccess policy to all of the IAM users but nothing happened.
I use the Django 1.8.2. Tried Django-ses but it did not work too (syntax error when running the tests, it does not support python 3?)
UPDATE
I changed the port to 587 and use USE_TLS True and now I can send_mail from django shell. I put the function in my app views.py :
def test_email(request):
send_mail("title", "content", "abc#gmail.com", ["def#gmail.com"], fail_silently=False)
return get_return_object(request, status_code=1)
and in urls.py I put this inside the urlpatterns :
url(r'^test_email/$', views.test_email, name="test_email"),
and when I visited the URL, nothing happens. I call the same function test_email from the shell and it works.
UPDATE
It turns out that I can also use port 465 and USE_SSL True and be able to send_mail from django shell. but still it does not work in views.py
2020 update
As the documentation says here: Django Email Documentation and Email_use_ssl
I am using Django 3.0 at this moment, and the documentation says that you can use
EMAIL_USE_SSL = True
... It is generally used on port 465
I make my think works and send emails using AWS SES and port 465 service using that line instead EMAIL_USE_TLS = True :)
If you use port 465:
Install django-smtp-ssl using pip
pip install django-smtp-ssl
then change EMAIL_BACKEND in settings.py as follows:
EMAIL_BACKEND = 'django_smtp_ssl.SSLEmailBackend'
If you use port 587:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

Categories