Skip to content

How it Works

TRAML can be used to send emails and SMS from your python code. All requests are sent synchronously and will return instant feedback if the message could be queued in Lime Marketing.

Send Email

Emails can be sent by providing your custom HTML and/or text content or by referencing a template in Lime Marketing. With TRAML emails you can use merge codes that will be replaced when sending by providing a dict of key/values. It is also possible to send attachments by creating an Attachment with bytes data, filename and mimetype. The helpers in the util module can be used to create attachments from a lime document/lime_file.

TRAML supports scheduled email and SMS send outs by setting the scheduled_send_date field of Email and Sms to the desired send time. Read more about scheduling here.

import limepkg_transactional_message_library.traml as traml

# TRAML support sending attachments from raw byte data
raw_attachment = traml.models.Attachment(
    file_data="räksmörgås".encode("utf-8"),
    file_name_with_extension="räksmörgåsfil.txt",
    mime_type="text/plain",
)

# The utils module has a helper method to create an attachment from a lime_file or document
lime_document = limeapp.limetypes.document.get(42)
lime_file = lime_document.properties.document.fetch()
lime_file_attachment = traml.util.create_attachment_from_lime_file(lime_file)

# TRAML support merge codes - it does a simple replace of the key with the value
merge_codes={
    "{{ name }}": "Bruce Wayne",
    "{{ company }}": "Wayne Industries"
}

# TRAML support custom headers that will be used when the email is sent
headers = {
    "x-my-header": "a value"
}

email = traml.models.Email(
    recipient_name="Bruce Wayne",
    recipient_email="[email protected]",
    from_name='Joker',
    from_email='[email protected]',
    subject='I know how you really are! 🦇',
    exclude_totaloptouts=True, # dont send email to recipient that is total optout
    exclude_previousbounce=True, # dont send email to recipient that have bounced previously
    scheduled_send_date=None, # pass a date to send at specific time or omit/None to send asap
    attachments=[raw_attachment, lime_file_attachment],
    merge_codes=merge_codes,
    headers=headers)

# TRAML helps you set the email properties (headers) for the must normal use cases
# The email is an auto reply - tell receiver to not send auto reply or out of office as response to this email
email.set_autoreply_headers()

# The email is in reponse to another email and the email client will then be able to stack them in the same conversation
email.set_in_reply_to_headers("<[email protected]>")

# The email is High, Normal or Low priority - High for the little red exclamation point
email.set_priority_headers(traml.models.EmailPriority.High)

tc = traml.TramlClient(application)

# TRAML can send the Email either by a template id or with a HTML content. The template id can be found in Lime Marketing.
# if you don't know the template id you can get that by using the get_template method in TRAML
send_result = tc.send_transactionmail_by_template(message=email, template_id=1337)
send_result = tc.send_transactionmail(message=email, html_content="my html content", 
                                            text_content="my text content")
The send_result will be a SentTransactionMailModel if the Email was queued successfully in Lime Marketing. If something went wrong an TramlError will be raised and any errors will be logged to the error log.

If you want to include a calendar booking in an Email it's possible to generate an url that lets the user download and save the booking to their calendar. The start_date and end_date properties supports timezone offset. In this example "+02:00" is used, meaning 2 hours ahead of UTC.

    tc = TramlClient(app=limeapp)   
    calendar_link = models.CalendarLink(
        start_date="2023-10-23T17:01:17.369732+02:00",
        end_date="2023-10-24T18:01:17.369732+02:00",
        summary="Birthday Party",
        description="Celebrate with us"
    )
    ical_url = tc.create_calendar_link(calendar_link=calendar_link)
    # add ical_url to your content with a merge variable or add it straight to the HTML
    merge_codes={
    "{{ calendar_booking_url }}": ical_url,
    "{{ event_name }}": "Birthday party!"
    }
    email = traml.models.Email(
        recipient_name="Bruce Wayne",
        recipient_email="[email protected]",
        from_name='Lime',
        from_email='[email protected]',
        subject='Welcome to our party',
        merge_codes=merge_codes,
        headers=headers)
    send_result = tc.send_transactionmail_by_template(message=email)

Send SMS

SMS can only be sent with custom content (no template support). When sending SMS a from_number must be provided. It can be either a text or phone number with a maximum of 11 characters - allowed characters are (a-z0-9åäöæøü_- and whitespace) With TRAML SMS you can use merge codes that will be replace when sending by providing a dict of key/values.

TRAML supports scheduled SMS send outs by setting the scheduled_send_date field to the desired send time.

import limepkg_transactional_message_library.traml as traml


# TRAML support merge codes - it does a simple replace of the key with the value
merge_codes={
    "{{ from }}": "The Joker"
}

message = traml.models.Sms(
    from_number="Joker", # this must be 2-11 chars a-zA-Z0-9
    destination_number="+4600001337",
    scheduled_send_date=None, # pass a date to send or omit to send asap
    merge_codes=merge_codes)

tc = traml.TramlClient(application)

# TRAML SMS doesn't support templates - only custom text content
send_result = tc.send_sms(message=sms, text="I know who you really are! Best regards from {{ from }}")
The send_result will be a SentTransactionSmsModel if the SMS was queued successfully in Lime Marketing. If something went wrong an TramlError will be raised and any errors will be logged to the error log.

Info

The TramlClient constructor can be initialized with a custom SendContext, Validator and application config. Read more about it here.

Scheduling

Both sending email and SMS supports scheduling. By omitting or setting scheduled_send_date to None or if the date has passed it will send immediately but sometimes you want to schedule the communication. To do this it's important to provide a non naive date and time that is time zone aware. Since recipients can be located in different time zones it's important to relate dates to a point in time rather than just a time that is local to the current Lime Marketing server time.

Schedule to send at a point in time

Example of how to get a correct date and time based on a specific time zone:

from datetime import datetime, timezone
import limepkg_transactional_message_library.traml.models as models
import pytz


# We want the email to be sent at 2022-03-14 15:00:00 Swedish Time
# List of timezones https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
tz_sweden = pytz.timezone("Europe/Stockholm")
send_date = tz_sweden.localize(
    datetime(year=2022, month=3, day=14, hour=15, minute=0, second=0)
)

message = models.Email(
    ....
    scheduled_send_date=send_date, # will result in "2022-03-14T15:00:00+0100
    ...
)

Schedule to Send at a Relative Time

To delay communication relative to the current time there's no need to involve specific time zones but rather use the current UTC date and time with the added delay.

from datetime import datetime, timedelta, timezone
import limepkg_transactional_message_library.traml.models as models


# We want the email to be sent one hour from now by adding one hour to the current utc time
send_date = datetime.now(timezone.utc) + timedelta(hours=1)

message = models.Email(
    ....
    scheduled_send_date=send_date,
    ....
)

Saving a copy of the sent email message in Lime CRM

If you want to save an exact copy of the message that the recipient has received you can set the include_email_data_in_webhook_payload parameter to True when sending an email with TRAML.

To access the email data you need to subscribe to the transactionmail.sent webhook. Use the TramlEmailMessage class to parse the TransactionMailContent property from the webhook payload.

Read more about this feature here

Testing

When using TRAML in code that are covered by tests you may need to make sure no actual messages are being sent or errors generated. Check out the test example on how to mock and assert the correct messages have been sent.

Back to top