How to send SES RawEmail with Attachment through PowerShell - amazon-web-services

I'm trying to design a PowerShell script that utilizes AWS SES to send a RawEmail with a .csv attachment, but information is scant on how to actually attach the attachment:
PS C:\Users\jsmith_prod\Desktop\SSMSScript> ls
Directory: C:\Users\jsmith_prod\Desktop\SSMS Script
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2/16/2023 2:00 PM 1096846 Inventory.csv
PS C:\Users\jsmith_prod\Desktop\SSMSScript> Send-SES2Email -FromEmailAddress jsmith#schwarma.com -Destination_ToAddress jsmith#schwarma.com -Raw_Data .\Inventory.csv
0100018661480af8-6a5939bd-5f9a-4f2f-9aa8-084cd872b9a8-000000
PS C:\Users\jsmith_prod\Desktop\SSMSScript>
When I try the above simple command, I only end up with an empty email, rather than an email with the attached .csv. According to AWS's documentation, attachments should be included under Raw_Data in order to highlight that this is a raw email. However, without any helpful error message, I can't figure out what's going wrong.

According to the Send-SES2Email documentation, the -Raw_Data argument is the raw email message itself, not an attachment. As you mentioned, attachments should be included under Raw_Data. The client must ensure that the message format complies with Internet email standards regarding email header fields, MIME types, and MIME encoding. The documentation defines criteria for raw messages and refers to RFC 5321 in that regard.
Please note, that the message body must contain a properly formatted, raw email message, with appropriate header fields and message body encoding. Although it's possible to construct the raw message manually within an application, it's much easier to do so using existing mail libraries. Check out this documentation for examples of how properly construct raw email message with an attachment. With Python it can look something like this (take note of how an attachment is handled):
import os
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
# Replace sender#example.com with your "From" address.
# This address must be verified with Amazon SES.
SENDER = "Sender Name <sender#example.com>"
# Replace recipient#example.com with a "To" address. If your account
# is still in the sandbox, this address must be verified.
RECIPIENT = "recipient#example.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 = "ConfigSet"
# If necessary, replace us-west-2 with the AWS Region you're using for Amazon SES.
AWS_REGION = "us-west-2"
# The subject line for the email.
SUBJECT = "Customer service contact info"
# The full path to the file that will be attached to the email.
ATTACHMENT = "path/to/customers-to-contact.xlsx"
# The email body for recipients with non-HTML email clients.
BODY_TEXT = "Hello,\r\nPlease see the attached file for a list of customers to contact."
# The HTML body of the email.
BODY_HTML = """\
<html>
<head></head>
<body>
<h1>Hello!</h1>
<p>Please see the attached file for a list of customers to contact.</p>
</body>
</html>
"""
# The character encoding for the email.
CHARSET = "utf-8"
# Create a multipart/mixed parent container.
msg = MIMEMultipart('mixed')
# Add subject, from and to lines.
msg['Subject'] = SUBJECT
msg['From'] = SENDER
msg['To'] = RECIPIENT
# 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 message
print(msg.as_string())

Related

Send emails by reading email address from S3

I am trying the following -
Read the email address from a csv file in S3, first column has email address, second column has the subject, third column has the body of the email.
Send email with the subject and body to the email address read from S3.
I was able to read the file in S3 into a DF using Lambda, but unable to send the email. Any ideas on how to do this using AWS services
you can use same lambda function to create smtp server of your own to send emails. e.g. while parsing data from the S3 csv file, for each entry in csv send email.
#!/usr/bin/env python
import smtplib
from email.mime.text import MIMEText
sender = 'xx#xx.com' # parsed data
receivers = ['yy#yy.com'] # parsed data
port = 1025
msg = MIMEText('email text') # parsed data
msg['Subject'] = 'Test mail'
msg['From'] = sender
msg['To'] = receivers
with smtplib.SMTP('localhost', port) as server:
server.sendmail(sender, receivers, msg.as_string())
print("email sent")
You can send emails from within a Lambda function by invoking the SES service. There is an example of creating a Lambda function (implemented in Java) that shows how to send an email message as part of a larger workflow created using AWS Step Functions. See this example:
Create AWS serverless workflows by using the AWS SDK for Java

An email sent using Python "smtplib" module arrives empty

Problem: When I send an email it does get sent from email1#hotmail.com to email2#hotmail.com but the email is empty. However, when I send the email using Gmail the email arrives with the content.
#app.route('/')
def email():
msg= 'Hello'
server = smtplib.SMTP("smtp-mail.outlook.com", 587)
server.starttls()
server.login("email1#hotmail.com", "Password1")
server.sendmail("email1#hotmail.com", "email2#hotmail.com", msg)
return 'Message Sent!'
Desirable result: I want to see the content when I open the email in email2#hotmail.com
I can't test it, but it might be necessary to add
"From: email1#hotmail.com\r\nTo: email2#hotmail.com\r\n\r\n"
in the beginning of msg.
So I would try with
msg = 'From: email1#hotmail.com\r\nTo: email2#hotmail.com\r\n\r\nHello'
and see if that works better.
Gmail might be more forgiving over such things than Hotmail.
Note also the blank line (\r\n\r\n) before the "Hello".

Django sending email with template

I want to send email using Django. In the mail body , I want to send Bootstrap "Card" which contain "Image" and HTML content.
Sending mail is successful. But, It is not showing the image in the received mail. Also, It is not in the Bootstrap "Card" format.
Please some one help me.
views.py
emailSubject = "Mail from XYZ.COM"
emailOfSender = EMAIL_HOST_USER
emailOfRecipient = viewed_bog.profile.user.email
html_content = render_to_string('receipt_email.html', {'item': viewed_bog, }, request=request)
try:
emailMessage = EmailMultiAlternatives(subject=emailSubject, body=html_content,
from_email=emailOfSender,
to=[emailOfRecipient, ], reply_to=[emailOfSender, ])
emailMessage.attach_alternative(html_content, "text/html")
emailMessage.send(fail_silently=False)
except SMTPException as e:
print('There was an error sending an email: ', e)
receipt_email.html
This is the HTML template containing Bootstrap 4 "Card" using Django-templating language. With in the Card I am having Image.
Now, I am able to send mail successfully. But Image is not showing in the received mail. and also, mail body is not in the "Card" format.
I will assume that you are loading the css from a bootstrap.css file and as most mail providers block loading css and js files for security reasons you should use inline styling in the template that you want to send.
Eventually this an online tool that i use when i want to compile regular css to inline css.
css inline tool

Airflow appending custom data to email alert

I want to append a runbook url to the airflow email alerts on failure. The default email sends other useful information such as airflow log link and I dont want to loose that. How can I achieve this.
I explored email operator but seems like it creates a new email and now I get 2 emails one for dag that failed and other from the email operator.
Is there a way to go about it ?
failure_email = EmailOperator (
task_id='failure-email',
name='failure-email',
to=['oncall#gmail.com'],
subject="T3 Failed",
html_content='<a>https://path/to/runbook</a>',
namespace= ,
dag=dag
)
You can customize the airflow email content by setting the html_content_template variable in the conf, the value of this var should be a path to a jinja2 file.
for example:
airflow.cfg -
[email]
html_content_template = /path/to/template
/path/to/template -
Try {{try_number}} out of {{max_tries + 1}}<br>
Exception:<br>{{exception_html}}<br>
Log: Link<br>
Host: {{ti.hostname}}<br>
Log file: {{ti.log_filepath}}<br>
Mark success: Link<br>
Runbook: <a>https://path/to/runbook</a>
(The default content of the airflow emails was taken from https://github.com/apache/airflow/blob/6e269570cd6dd2d434a3c63ca0db9f1a59dea847/airflow/models/taskinstance.py#L1263).

Django: Attach ICS file with Meeting Response

I am trying to attach ICS files to emails sent via Django that when received includes the option to Accept, Tentative, Decline, Propose New Time in Outlook.
meeting-response
Currently, I am able to attach the ICS file to the email however it is not providing the options I stated above.
ics attachment
Below is how I am handling the ICS file, attaching it, and sending the email:
#OPEN 'invite.ics' write generated ICS to file
f = open(os.path.dirname(os.path.realpath(__file__)) + '/attachments/invite.ics', 'w')
f.write(ical)
f.close()
#COMPOSE EMAIL
msg = EmailMultiAlternatives(subject, description, fro, attendees)
#Attach ICS file
msg.attach_file(os.path.dirname(os.path.realpath(__file__)) + '/attachments/invite.ics')
#for HTML email template
msg.attach_alternative(html_message, "text/html")
msg.send()
You seem to be missing a proper content-type with a METHOD indicating the type of iTIP message. See Multipart email with text and calendar: Outlook doesn't recognize ics