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()
Asked By: Tom

||

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.

Answered By: Mark B
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.