AWS Lambda new line using boto3
Question:
This should be quite straightforward but I’m a bit stuck. I have a Lambda function in AWS that sends out daily email with FX rates, I’m just trying to add a new line in the body of the email that gets sent out using boto3 but ‘n’ doesn’t seem to work, any thoughts? I have copied the code below with some placeholders for sender and receiver email addresses.
import yfinance as yf
import json
import boto3
class LambdaHandler:
def __init__(self,event, context):
self.event = event
self.context = context
self.FX_rates = {"eur_usd": yf.Ticker('EURUSD=X').history(period='30d')['Close'],
"gbp_usd": yf.Ticker('GBPUSD=X').history(period='30d')['Close'],
"gbp_eur": yf.Ticker('GBPEUR=X').history(period='30d')['Close'],
"gbp_aud": yf.Ticker('GBPAUD=X').history(period='30d')['Close']
}
# Daily change
self.Dailys = {fx: (fx_data[-1]/fx_data[-2]-1)*100 for fx, fx_data in self.FX_rates.items()}
# Weekly change
self.Weeklys = {fx: (fx_data[-1]/fx_data[-7]-1)*100 for fx, fx_data in self.FX_rates.items()}
# Monthly change
self.Monthlys = {fx: (fx_data[-1]/fx_data[-30]-1)*100 for fx, fx_data in self.FX_rates.items()}
# FX rates formatted
self.rounded_FX = {
"eur_usd": round(self.FX_rates['eur_usd'][0],2),
"gbp_usd": round(self.FX_rates['gbp_usd'][0],2),
"gbp_eur": round(self.FX_rates['gbp_eur'][0],2),
"gbp_aud": round(self.FX_rates['gbp_aud'][0],2)
}
def to_f_statement(self, rate):
return "{}%".format("%.2f" % rate)
def send_email(self):
ses = boto3.client("ses", region_name="eu-west-2")
sent_from = "SENDER EMAIL ADDRESS"
receiver_email = "RECEIVER EMAIL ADDRESS"
body = f'Current FX rates: EUR to USD {self.rounded_FX["eur_usd"]}, GBP to USD {self.rounded_FX["gbp_usd"]}, GBP to EUR {self.rounded_FX["gbp_eur"]}, GBP to AUD {self.rounded_FX["gbp_aud"]}. '
'n'
f'Daily changes: EUR to USD {self.to_f_statement(self.Dailys["eur_usd"])}, GBP to USD {self.to_f_statement(self.Dailys["gbp_usd"])}, GBP to EUR {self.to_f_statement(self.Dailys["gbp_eur"])},'
f'GBP to AUD {self.to_f_statement(self.Dailys["gbp_aud"])}'
f'n'
f'Weekly changes: EUR to USD {self.to_f_statement(self.Weeklys["eur_usd"])}, GBP to USD {self.to_f_statement(self.Weeklys["gbp_usd"])}, GBP to EUR {self.to_f_statement(self.Weeklys["gbp_eur"])},'
f' GBP to AUD {self.to_f_statement(self.Weeklys["gbp_aud"])}'
f'n'
f' Monthly changes: EUR to USD {self.to_f_statement(self.Monthlys["eur_usd"])}, GBP to USD {self.to_f_statement(self.Monthlys["gbp_usd"])}, GBP to EUR {self.to_f_statement(self.Monthlys["gbp_eur"])},'
f' GBP to AUD {self.to_f_statement(self.Monthlys["gbp_aud"])}'
CHARSET = "UTF-8"
html = """
%s
""" % (body)
response = ses.send_email(
Destination={
"ToAddresses": [
receiver_email,
],
},
Message={
"Body": {
"Html": {
"Charset": CHARSET,
"Data": html,
}
},
"Subject": {
"Charset": CHARSET,
"Data": "Daily FX rates",
},
},
Source=sent_from,
)
return {
'statusCode': 200,
'body': json.dumps('Ready to go!')
}
def lambda_handler(event, context):
return LambdaHandler(event, context).send_email()
Answers:
This is because you are sending a plain text email, but passing the email body into the Html
attribute instead of the Text
attribute. So the email is being sent as HTML and your email client is rendering it as HTML. Newlines are ignored in HTML.
You either need to change your newline n
characters into HTML <br>
line break tags, or you need to just pass your current email body as Text
instead of Html
.
This should be quite straightforward but I’m a bit stuck. I have a Lambda function in AWS that sends out daily email with FX rates, I’m just trying to add a new line in the body of the email that gets sent out using boto3 but ‘n’ doesn’t seem to work, any thoughts? I have copied the code below with some placeholders for sender and receiver email addresses.
import yfinance as yf
import json
import boto3
class LambdaHandler:
def __init__(self,event, context):
self.event = event
self.context = context
self.FX_rates = {"eur_usd": yf.Ticker('EURUSD=X').history(period='30d')['Close'],
"gbp_usd": yf.Ticker('GBPUSD=X').history(period='30d')['Close'],
"gbp_eur": yf.Ticker('GBPEUR=X').history(period='30d')['Close'],
"gbp_aud": yf.Ticker('GBPAUD=X').history(period='30d')['Close']
}
# Daily change
self.Dailys = {fx: (fx_data[-1]/fx_data[-2]-1)*100 for fx, fx_data in self.FX_rates.items()}
# Weekly change
self.Weeklys = {fx: (fx_data[-1]/fx_data[-7]-1)*100 for fx, fx_data in self.FX_rates.items()}
# Monthly change
self.Monthlys = {fx: (fx_data[-1]/fx_data[-30]-1)*100 for fx, fx_data in self.FX_rates.items()}
# FX rates formatted
self.rounded_FX = {
"eur_usd": round(self.FX_rates['eur_usd'][0],2),
"gbp_usd": round(self.FX_rates['gbp_usd'][0],2),
"gbp_eur": round(self.FX_rates['gbp_eur'][0],2),
"gbp_aud": round(self.FX_rates['gbp_aud'][0],2)
}
def to_f_statement(self, rate):
return "{}%".format("%.2f" % rate)
def send_email(self):
ses = boto3.client("ses", region_name="eu-west-2")
sent_from = "SENDER EMAIL ADDRESS"
receiver_email = "RECEIVER EMAIL ADDRESS"
body = f'Current FX rates: EUR to USD {self.rounded_FX["eur_usd"]}, GBP to USD {self.rounded_FX["gbp_usd"]}, GBP to EUR {self.rounded_FX["gbp_eur"]}, GBP to AUD {self.rounded_FX["gbp_aud"]}. '
'n'
f'Daily changes: EUR to USD {self.to_f_statement(self.Dailys["eur_usd"])}, GBP to USD {self.to_f_statement(self.Dailys["gbp_usd"])}, GBP to EUR {self.to_f_statement(self.Dailys["gbp_eur"])},'
f'GBP to AUD {self.to_f_statement(self.Dailys["gbp_aud"])}'
f'n'
f'Weekly changes: EUR to USD {self.to_f_statement(self.Weeklys["eur_usd"])}, GBP to USD {self.to_f_statement(self.Weeklys["gbp_usd"])}, GBP to EUR {self.to_f_statement(self.Weeklys["gbp_eur"])},'
f' GBP to AUD {self.to_f_statement(self.Weeklys["gbp_aud"])}'
f'n'
f' Monthly changes: EUR to USD {self.to_f_statement(self.Monthlys["eur_usd"])}, GBP to USD {self.to_f_statement(self.Monthlys["gbp_usd"])}, GBP to EUR {self.to_f_statement(self.Monthlys["gbp_eur"])},'
f' GBP to AUD {self.to_f_statement(self.Monthlys["gbp_aud"])}'
CHARSET = "UTF-8"
html = """
%s
""" % (body)
response = ses.send_email(
Destination={
"ToAddresses": [
receiver_email,
],
},
Message={
"Body": {
"Html": {
"Charset": CHARSET,
"Data": html,
}
},
"Subject": {
"Charset": CHARSET,
"Data": "Daily FX rates",
},
},
Source=sent_from,
)
return {
'statusCode': 200,
'body': json.dumps('Ready to go!')
}
def lambda_handler(event, context):
return LambdaHandler(event, context).send_email()
This is because you are sending a plain text email, but passing the email body into the Html
attribute instead of the Text
attribute. So the email is being sent as HTML and your email client is rendering it as HTML. Newlines are ignored in HTML.
You either need to change your newline n
characters into HTML <br>
line break tags, or you need to just pass your current email body as Text
instead of Html
.