Unable to set X-SES-CONFIGURATION-SET headers in aws ses - python-3.x

I am using this script to send email using AWS SES and I am able to receive email in my inbox but I am not able to see X-SES-CONFIGURATION-SET header in the received email. I also tried using Simple email body type with ConfigurationSetName still no luck. Any help is highly appreciated.
import boto3
from botocore.exceptions import ClientError
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
# Replace sender#example.com with your "From" address.
# This address must be verified with Amazon SES.
SENDER = "Niranj Raja <niranj#xxx.com>"
# Replace recipient#example.com with a "To" address. If your account
# is still in the sandbox, this address must be verified.
RECIPIENT = "niranj#xxx.com"
# Specify a configuration set. If you do not want to use a configuration
# set, comment the following variable, and the
# ConfigurationSetName=CONFIGURATION_SET argument below.
CONFIGURATION_SET = "test-me"
# The subject line for the email.
SUBJECT = "Amazon SES Test (SDK for Python)"
# The email body for recipients with non-HTML email clients.
BODY_TEXT = ("Amazon SES Test (Python)\r\n"
"This email was sent with Amazon SES using the "
"AWS SDK for Python (Boto)."
)
# The HTML body of the email.
BODY_HTML = """<html>
<head></head>
<body>
<h1>Amazon SES Test (SDK for Python)</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-python/'>
AWS SDK for Python (Boto)</a>.</p>
</body>
</html>
"""
# The character encoding for the email.
CHARSET = "UTF-8"
msg = MIMEMultipart('mixed')
# Add subject, from and to lines.
msg['Subject'] = SUBJECT
msg['From'] = SENDER
msg['To'] = RECIPIENT
#msg['X-SES-CONFIGURATION-SET'] = CONFIGURATION_SET
msg.add_header('X-SES-CONFIGURATION-SET', CONFIGURATION_SET)
print(dir(msg))
print('')
# Create a multipart/alternative child container.
msg_body = MIMEMultipart('alternative')
print(dir(msg_body))
# Encode the text and HTML content and set the character encoding. This step is
# necessary if you're sending a message with characters outside the ASCII range.
textpart = MIMEText(BODY_TEXT.encode(CHARSET), 'plain', CHARSET)
htmlpart = MIMEText(BODY_HTML.encode(CHARSET), 'html', CHARSET)
msg_body.attach(textpart)
msg_body.attach(htmlpart)
# Create a new SES resource and specify a region.
client = boto3.client(
'sesv2',
aws_access_key_id='test',
aws_secret_access_key='test1',
region_name='region-10'
)
# Try to send the email.
try:
# Provide the contents of the email.
response = client.send_email(
FromEmailAddress=SENDER,
Destination={
'ToAddresses': [
RECIPIENT,
],
},
Content={
'Raw': {
'Data': msg_body.as_string()
}
}
)
print(response)
# Display an error if something goes wrong.
except ClientError as e:
print(e.response['Error']['Message'])
else:
print("Email sent! Message ID:"),
print(response['MessageId'])

Related

How do I avoid accumulating gmails with the same subject using SMTPLIB and Python

When I send files with the same subject using the code the emails accumulate in the inbox.
What I want to do is that these do not accumulate and are sent one by one with the same subject.
from email.mime.text import MIMEText
import smtplib
import smtplib, ssl
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
receiver = 'receiver'
sender = 'sender'
senders_password = 'password_application_sender'#This password is a password of application, this option activate in manager account of his gmail account
file = "path of file"
subject = 'subject' #This subject always is the same
mensaje = MIMEMultipart("alternative")
mensaje["Subject"] = subject
mensaje["From"] = sender
mensaje["To"] = receiver
html = f"""
<html>
<body>
Hi this is a email with a attachment
</body>
</html>
"""
body_html = MIMEText(html, "html")
mensaje.attach(body_html)
with open(file, "rb") as attachment:
content = MIMEBase("application","octet-stream")
content.set_payload(attachment.read())
encoders.encode_base64(content)
content.add_header(
"Content-Disposition",
f"attachment; filename= {file}",
)
mensaje.attach(content)
text = mensaje.as_string()
context = ssl.create_default_context()
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
server.login(sender, senders_password)
server.sendmail(sender, receiver, text)
server.quit()
print("Email Send")
How I receive the email and How should it get

How would I save a file received by discord.py

I was working on my discord bot trying to implement a email feature where you imbed a file and then the discord bot downloads it and sends it back out to the server. I came across the issue where I have no idea how I would begin to save the file. You can find my code at https://github.com/Omar-Alabdalla/DiscordBot. the specific files that have the emailing feature are mailFunctions(discord commands part) and basicMail(email commands part).
I looked through the docs of nextcord.py and couldn't find any simple way that I could understand. I probably just missed what I was supposed to find though.
discord command Code:
#commands.command()
async def mailFile(self, ctx, *stuff):
# received if else statement from stackoverflow: https://stackoverflow.com/questions/65169339/download-csv-file-sent-by-user-discord-py
if str(ctx.attachments) == "[]": # This checks if there is an attachment on the message
return "You didn't include a file"
else:
await save("mailFile
The mailing class code:
def sendFileMail(rmail, message):
mail_content = '''Hello,
This is a test mail.
In this mail we are sending some attachments.
The mail is sent using Python SMTP library.
Thank You
'''
# Setup the MIME
message = MIMEMultipart()
message['From'] = sender_email
message['To'] = rmail
message['Subject'] = 'A test mail sent by Python. It has an attachment.'
# The subject line
# The body and the attachments for the mail
message.attach(MIMEText(mail_content, 'plain'))
attach_file_name = 'TP_python_prev.pdf'
attach_file = open(attach_file_name, 'rb') # Open the file as binary mode
payload = MIMEBase('application', 'octate-stream')
payload.set_payload(attach_file.read())
encoders.encode_base64(payload) # encode the attachment
# add payload header with filename
payload.add_header('Content-Decomposition', 'attachment', filename=attach_file_name)
message.attach(payload)
# Create SMTP session for sending the mail
session = smtplib.SMTP('smtp.gmail.com', 587) # use gmail with port
session.starttls() # enable security
session.login(sender_email, password) # login with mail_id and password
text = message.as_string()
session.sendmail(sender_email, rmail, text)
session.quit()
print('Mail Sent')
Apologies for not including code prior First time posting on stack overflow
See Attachment.save: https://nextcord.readthedocs.io/en/latest/api.html?highlight=attachment#nextcord.Attachment.save
for attachment in ctx.message.attachments:
await attachment.save(attachment.filename)

How do I add an attachment to a daily scheduled email in AWS, SES, Lambda, Cloudwatch

1). I have found a piece of code (below) in Node.js which allows me to send an email alert at 9am which works fine. I need to further develop this so that it will attach the latest file from an S3 bucket.
2). I have found other code in Python which will send an email with the file attached as soon as it is uploaded to the S3 bucket.
I can't get the extra functionality from 2 to work in 1.
Below is the code for the function which successfully schedules an email but I need to be able to attach the latest file in an S3 bucket. I also don't know the name of the file as it will be uploaded by someone else.
All I need to do is to send the latest file in the S3 bucket as an attachment at 9am daily.
I have the Cloudwatch schedule feature already setup.
const AWS = require('aws-sdk');
AWS.config.update({
region: 'eu-west-2'
})
const ses = new AWS.SES();
const s3 = new AWS.S3();
exports.handler = async (event) => {
const params = {
Destination: {
ToAddresses: ['abc#abc.com']
},
Message: {
Subject: {Data: 'Daily Email'},
Body: {
Text: {Data: 'Hello: \n\n Good Morning: Here is your 9am Alert!!! \n\n'}
}
},
Source: 'xyz#xyz.com'
};
await ses.sendEmail(params).promise().then(response => {
console.log('Successfully sent email!!!');
}, error => {
console.error('An error occured while attempting to send email: ', error);
})
};
I managed to get a Python version working, which sends the attachment, but for some reason it doesn't include the file name to the attachment? It gives the attachment name as a string of random characters.
Does anyone know how to include the file attachment name to the attached file & which part of my code would be causing the issue? I know the attachment name as "TEST.pdf" can I just add the name to the successfully attached file?
import boto3
import os.path
import email
from botocore.exceptions import ClientError
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
def lambda_handler(event, context):
ses = boto3.client("ses")
s3 = boto3.client("s3")
AWS_REGION = "aws_region"
bucket_name = 'testing'
object_name = 'TEST.pdf'
fileObj = s3.get_object( Key=object_name, Bucket='testing')
key = str(fileObj)
sender = "abc#abc.com"
to = "xyz#xyz.com"
subject = 'Email from abc'
body = """Hello, xyz Please see the attached file related to recent submission.
<br>
This email is from blahblahblah:
"""
file_name = os.path.basename(key)
tmp_file_name = '/tmp/' +file_name
s3.download_file(bucket_name, object_name, tmp_file_name)
ATTACHMENT= tmp_file_name
# att= tmp_file_name
# The email body for recipients with non-HTML email clients.
BODY_TEXT = "Hello, xyz Please see the attached file related to recent submission."
# The HTML body of the email.
BODY_HTML = """\
<html>
<head></head>
<body>
<h1>Hello!!!</h1>
<p>Please see the attached file related to TEST.pdf latest upload to S3 Bucket.</p>
</body>
</html>
"""
# The character encoding for the email.
CHARSET = "utf-8"
# Create a new SES resource and specify a region.
client = boto3.client('ses',region_name=AWS_REGION)
# Create a multipart/mixed parent container.
msg = MIMEMultipart('mixed')
# Add subject, from and to lines.
msg['Subject'] = subject
msg['From'] = sender
msg['To'] = to
# Create a multipart/alternative child container.
msg_body = MIMEMultipart('alternative')
# Encode the text and HTML content and set the character encoding. This step is
# necessary if you're sending a message with characters outside the ASCII range.
textpart = MIMEText(BODY_TEXT.encode(CHARSET), 'plain', CHARSET)
htmlpart = MIMEText(BODY_HTML.encode(CHARSET), 'html', CHARSET)
# Add the text and HTML parts to the child container.
msg_body.attach(textpart)
msg_body.attach(htmlpart)
# Define the attachment part and encode it using MIMEApplication.
att = MIMEApplication(open(ATTACHMENT, 'rb').read())
# Add a header to tell the email client to treat this part as an attachment,
# and to give the attachment a name.
att.add_header('Content-Disposition','attachment',filename=os.path.basename(ATTACHMENT))
# Attach the multipart/alternative child container to the multipart/mixed
# parent container.
msg.attach(msg_body)
# Add the attachment to the parent container.
msg.attach(att)
print(msg)
try:
#Provide the contents of the email.
response = client.send_raw_email(
Source=sender,
Destinations=[
to
],
RawMessage={
'Data':msg.as_string(),
},
# ConfigurationSetName=CONFIGURATION_SET
)
# Display an error if something goes wrong.
except ClientError as e:
print(e.response['Error']['Message'])
else:
print("Email sent! Message ID:"),
print(response['MessageId'])

Sending a gmail message

im trying to send a gmail message with the following code:
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import base64
def create_message(sender, to, subject, message_text):
"""Create a message for an email.
Args:
sender: Email address of the sender.
to: Email address of the receiver.
subject: The subject of the email message.
message_text: The text of the email message.
Returns:
An object containing a base64url encoded email object.
"""
message = MIMEText(message_text)
message['to'] = to
message['from'] = sender
message['subject'] = subject
#return {'raw': base64.urlsafe_b64encode(message.as_string())}
b64_bytes = base64.urlsafe_b64encode(message.as_bytes())
b64_string = b64_bytes.decode()
#body = {'raw': b64_string}
return {'raw': b64_string}
s = "email"
t = "email"
sub = "test subject"
m = "message test"
create_message(s,t,sub,m)
where s = my email(replaced with "email" in this example and t = my other email (again replaced))
It doesnt kick out any errors but doesnt send the message.
Also this code didnt work:
#return {'raw': base64.urlsafe_b64encode(message.as_string())}
as it produced the following error: TypeError: a bytes-like object is required, not 'str'
"I solved that" with this:
b64_bytes = base64.urlsafe_b64encode(message.as_bytes())
b64_string = b64_bytes.decode()
#body = {'raw': b64_string}
return {'raw': b64_string}
edit(1): I do have credentials.json and passed the google api example
Needed to create client_secret.json and paste my credentials there, ctrc+c, ctrl+v an old example and update it to python 3.x, resolved base 64 issue and it works :)
import httplib2
import os
from apiclient import discovery
import oauth2client
from oauth2client import client
from oauth2client import tools
from oauth2client import file
try:
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
SCOPES = 'https://mail.google.com/'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Gmail API Quickstart'
def get_credentials():
"""Gets valid user credentials from storage.
If nothing has been stored, or if the stored credentials are invalid,
the OAuth2 flow is completed to obtain the new credentials.
Returns:
Credentials, the obtained credential.
"""
home_dir = os.path.expanduser('~')
credential_dir = os.path.join(home_dir, '.credentials')
if not os.path.exists(credential_dir):
os.makedirs(credential_dir)
credential_path = os.path.join(credential_dir,
'gmail-quickstart.json')
store = oauth2client.file.Storage(credential_path)
credentials = store.get()
if not credentials or credentials.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
flow.user_agent = APPLICATION_NAME
if flags:
credentials = tools.run_flow(flow, store, flags)
else: # Needed only for compatability with Python 2.6
credentials = tools.run(flow, store)
print('Storing credentials to ' + credential_path)
return credentials
import base64
from email.mime.audio import MIMEAudio
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import mimetypes
from httplib2 import Http
from apiclient import errors
from apiclient.discovery import build
credentials = get_credentials()
service = build('gmail', 'v1', http=credentials.authorize(Http()))
def SendMessage(service, user_id, message):
"""Send an email message.
Args:
service: Authorized Gmail API service instance.
user_id: User's email address. The special value "me"
can be used to indicate the authenticated user.
message: Message to be sent.
Returns:
Sent Message.
"""
try:
message = (service.users().messages().send(userId=user_id, body=message)
.execute())
print('Message Id: %s' % message['id'])
return message
except errors.HttpError as error:
print('An error occurred: %s' % error)
def CreateMessage(sender, to, subject, message_text):
"""Create a message for an email.
Args:
sender: Email address of the sender.
to: Email address of the receiver.
subject: The subject of the email message.
message_text: The text of the email message.
Returns:
An object containing a base64 encoded email object.
"""
message = MIMEText(message_text)
message['to'] = to
message['from'] = sender
message['subject'] = subject
b64_bytes = base64.urlsafe_b64encode(message.as_bytes())
b64_string = b64_bytes.decode()
#body = {'raw': b64_string}
return {'raw': b64_string}
#return {'raw': base64.b64encode(message.as_string())}
testMessage = CreateMessage("email","email","test_subject","test_message")
testSend = SendMessage(service, 'me', testMessage)
emails replaced with email in line 106 (second from bottom)

How to send an email without login to server in Python

I want to send an email without login to server in Python. I am using Python 3.6.
I tried some code but received an error. Here is my Code :
import smtplib
smtpServer='smtp.yourdomain.com'
fromAddr='from#Address.com'
toAddr='to#Address.com'
text= "This is a test of sending email from within Python."
server = smtplib.SMTP(smtpServer)
server.set_debuglevel(1)
server.sendmail(fromAddr, toAddr, text)
server.quit()
I expect the mail should be sent without asking user id and password but getting an error :
"smtplib.SMTPSenderRefused: (530, b'5.7.1 Client was not authenticated', 'from#Address.com')"
I am using like this. It's work to me in my private SMTP server.
import smtplib
host = "server.smtp.com"
server = smtplib.SMTP(host)
FROM = "testpython#test.com"
TO = "bla#test.com"
MSG = "Subject: Test email python\n\nBody of your message!"
server.sendmail(FROM, TO, MSG)
server.quit()
print ("Email Send")
import win32com.client as win32
outlook=win32.Dispatch('outlook.application')
mail=outlook.CreateItem(0)
mail.To='To address'
mail.Subject='Message subject'
mail.Body='Message body'
mail.HTMLBody='<h2>HTML Message body</h2>' #this field is optional
# To attach a file to the email (optional):
attachment="Path to the attachment"
mail.Attachments.Add(attachment)
mail.Send()
The code below worked for me.
First, I opened/enabled Port 25 through Network Team and used it in the program.
import smtplib
smtpServer='smtp.yourdomain.com'
fromAddr='from#Address.com'
toAddr='to#Address.com'
text= "This is a test of sending email from within Python."
server = smtplib.SMTP(smtpServer,25)
server.ehlo()
server.starttls()
server.sendmail(fromAddr, toAddr, text)
server.quit()
First, you have to have a SMTP server to send an email. When you don't have one, usually outlook's server is used. But outlook only accepts authenticated users, so if you don't want to login into the server, you have to pick a server that doesn't need authentication.
A second approach is to setup an internal SMTP server. After you setup the internal SMTP server, you can use the "localhost" as the server to send the email. Like this:
import smtplib
receiver = 'someonesEmail#hisDomain.com'
sender = 'yourEmail#yourDomain.com'
smtp = smtplib.SMTP('localhost')
subject = 'test'
body = 'testing plain text message'
msg = 'subject: ' + subject + ' \n\n' + body
smtp.sendmail('sender', receiver, msg)

Resources