Step-by-step instructions to send email with OCI Email Delivery

February 17, 2022 | 13 minute read
Cody Brinkman
Cloud Architect
Text Size 100%:

Oracle Cloud Infrastructure (OCI) Email Delivery is an email sending service and Simple Mail Transfer Protocol (SMTP) relay that provides a fast and reliable managed solution for sending both high volume bulk and transactional emails. Email Delivery provides the tools necessary to send application-generated email for mission-critical communications such as receipts, fraud detection alerts, multi-factor identity verification, and password resets. In this blog, I guide you through the process of sending emails with Email Delivery and give background on email best practices and authentication.

Who should use Email Delivery?

Any business or cloud-based application that needs to send messages to users’ inbox in a cost-effective way should use Email Delivery. Email Delivery is a highly scalable, cost-effective, and reliable service that eliminates the complexity and expense of building an in-house email delivery solution. If you’re currently using Amazon Simple Email Service (SES) or SendGrid, you can think of OCI Email Delivery as a similar service.

Best of all, it’s simple to setup and begin using!

Prerequisites

First, you need access to an OCI environment. If you don’t have one, you can easily create your own trial with US$300 in free credits and access to our Always Free services.

When you have an environment, ensure that your user has been assigned to a group with permissions to manage the email-family resources. Creating a user is security best practice instead of using your Console user that already has permissions assigned to it. If you need help, view the Set Up Permissions section in the documentation to create a group and grant it the proper permissions.

Finally, you need a DNS domain to publish your domain keys identified mail (DKIM) and sender policy framework (SPF) records. While DKIM and SPF aren’t required to send emails, we highly recommend setting them up. We dive deeper into DKIM and SPF later.

Sending email

Generate SMTP credentials

SMTP credentials are necessary to send email through Email Delivery. Each user is limited to a maximum of two SMTP credentials. So, if you need more than two, create another user.

Log into the Oracle Cloud Console and navigate to User Settings.


Figure 1: Navigating to user settings

Scroll down to SMTP Credentials and click to generate one.


Figure 2: Generating SMTP credentials​​​​​

Copy the username and password. For security reasons, you can’t retrieve the password after closing the dialog box.


Figure 3: Copying SMTP credential username and password

Create your email domain

An email domain lets you set up important authentication measures for sending email. Under Developer Services, select Application Integration and Email Delivery. Click Email Domains and create a domain. If setting up DKIM and SPF, choose a DNS domain that you own or control and plan to use for the sending email address.


Figure 4: My email domain

Set up DKIM

DKIM is an email authentication technique that allows the receiver to verify the owner of an email domain. It gives the email a digital signature, which is a header field containing all the signature and key-fetching data. Email receivers, like Gmail and Microsoft, detect the DKIM signature and run a DNS query to search for the public key for that domain. If found, it decrypts the signature and confirms that it was created with the matching private key. So, implementing DKIM improves email deliverability and can protect your domain against malicious emails sent on behalf of your domain.

Now that you know what DKIM is, navigate to it in your zone and add one.


Figure 5: Navigating to DKIM

 

We use the DKIM selector for this DKIM key, which must be globally unique for your domain. We recommend using a regional indicator and date portion as part of the selector, such as prefix-region-YYYYMMDD, to help with future key rotation. Generate the DKIM record and then click Create DKIM.


Figure 6: Creating DKIM record

We now need to configure our DNS domain. Go to your zone and create the CNAME record with the value it gives you.


Figure 7: Creating DKIM CNAME record

If done correctly, your DKIM signing status changes to Active. Mine took a minute or so to propagate.

Depending on the update type, updates to your DNS records can take up to 24 hours to propagate globally.


Figure 8: DKIM signing status

Rotate your DKIM keys at least every six months. Rotation reduces the risk of active keys being compromised, either by attackers cracking or stealing them. For more information about rotating keys and DKIM in general, see M3AAWG DKIM Key Rotation Best Common Practices.

Create an approved sender

You need an approved sender for all “From” addresses sending mail through OCI. Otherwise, mail is rejected. Every sender email address must be registered to use it for Email Delivery.

Note the following details about approved senders:

  • An approved sender is associated with a compartment and only exists in the region where it was configured. If you create an approved sender in the US West (Phoenix) region, you can’t send email through the US East (Ashburn) region with that sender.

  • Don’t create approved senders in the root compartment. If you do, you need to create a policy to manage approved senders in the entire tenancy. Creating approved senders in a compartment other than the root allows the policy to be specific to that compartment.

  • Using multiple addresses in the email “From:” header is discouraged because it increases the possibility that your mail is placed in a spam folder or discarded. A best practice for the “From:” address is to match the header “From:” address when you submit mail to Email Delivery. If you use mismatched addresses, it reduces performance of your emails because both addresses need to be authorized as approved senders.

  • Approved senders are unique to tenancies. If you create a duplicate sender, the service returns a 409 Conflict error.

Under DKIM, you can see Approved Senders. Create one.


Figure 9: Creating approved sender

Configure SPF on your approved sender domain

SPF allows you to state which email servers are permitted to send email on behalf of your domain. Email receivers use SPF to detect email spoofing. You can implement it by publishing a special TXT record to your domain’s DNS records. The receiving mail server checks the SPF record of the sending domain to verify the email’s source IP address is authorized to send from that domain. Without SPF, a spam or phishing email can be spoofed to appear that it comes from a legitimate domain.

Navigate to your approved sender. Under the three-dot menu, select View SPF.


Figure 10: Viewing SPF record values

Choose your sending location and create a DNS TXT record with the corresponding value. I’m using Americas.


Figure 11: Creating SPF TXT record

It can take some time, but your domain now shows DKIM Signing and SPF working.


Figure 12: DKIM and SPF working

Configure the SMTP connection

Navigate to Configuration to access SMTP sending information to configure the connection in your system.


Figure 13: SMTP sending information

The following information is displayed:

  • Public endpoint: The public endpoint used to send email to this region

  • SMTP ports: The SMTP ports used to accept email. Email Delivery supports TLS on port 25 or 587 (recommended).

  • Security: Indicates if TLS is being used. Customers must encrypt email while in transit to Email Delivery.

Send mail

Now that our email domain is set up and secured, we can begin sending mail! You can use your own SMTP library or product, such as Postfix or Sendmail. I’m using a simple Python script as an example. You can find details for testing with Python in the documentation.

The following code block shows the skeleton code:

# python script for sending SMTP configuration with Oracle Cloud Infrastructure Email Delivery
import smtplib 
import email.utils
from email.message import EmailMessage
import ssl

# Replace sender@example.com with your "From" address.
# This address must be verified.
# this is the approved sender email
SENDER = 'sender@example.com'
SENDERNAME = 'Sender Name'
 
# 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'
 
# Replace the USERNAME_SMTP value with your Email Delivery SMTP username.
USERNAME_SMTP = 'ocid1.user.oc1..@ocid1.tenancy.oc1...vf.com'
 
# Put the PASSWORD value from your Email Delivery SMTP password into the following file.
PASSWORD_SMTP_FILE = 'ociemail.config'
 
# If you’re using Email Delivery in a different region, replace the HOST value with an appropriate SMTP endpoint.
# Use port 25 or 587 to connect to the SMTP endpoint.
HOST = "smtp.us-ashburn-1.oraclecloud.com"
PORT = 587
 
# The subject line of the email.
SUBJECT = 'Email Delivery Test (Python smtplib)'
 
# The email body for recipients with non-HTML email clients.
BODY_TEXT = (
             "This email was sent through the Email Delivery SMTP "
             "Interface using the Python smtplib package."
            )
 
# get the password from a named config file ociemail.config
with open(PASSWORD_SMTP_FILE) as f:
    password_smtp = f.readline().strip()

# create message container
msg = EmailMessage()
msg['Subject'] = SUBJECT
msg['From'] = email.utils.formataddr((SENDERNAME, SENDER))
msg['To'] = RECIPIENT

# make the message multi-part alternative, making the content the first part
msg.add_alternative(BODY_TEXT, subtype='text')

# Try to send the message.
try: 
    server = smtplib.SMTP(HOST, PORT)
    server.ehlo()
    # most python runtimes default to a set of trusted public CAs that will include the CA used by OCI Email Delivery.
    # However, on platforms lacking that default (or with an outdated set of CAs), customers may need to provide a capath that includes our public CA.
    server.starttls(context=ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH, cafile=None, capath=None))
    # smtplib docs recommend calling ehlo() before & after starttls()
    server.ehlo()
    server.login(USERNAME_SMTP, password_smtp)
    # our requirement is that SENDER is the same as From address set previously
    server.sendmail(SENDER, RECIPIENT, msg.as_string())
    server.close()
# Display an error message if something goes wrong.
except Exception as e:
    print(f"Error: {e}")
else:
    print("Email successfully sent!")

The following block shows my script. named ociemail.py:


# python script for sending SMTP configuration with Oracle Cloud Infrastructure Email Delivery
import smtplib 
import email.utils
from email.message import EmailMessage
import ssl

# Replace sender@example.com with your "From" address.
# This address must be verified.
# this is the approved sender email
SENDER = 'BlogTestSender@elcaroydoc.com'
SENDERNAME = 'Blog Test Sender'
 
# Replace recipient@example.com with a "To" address. If your account
# is still in the sandbox, this address must be verified.
RECIPIENT = 'cody.brinkman@oracle.com'
 
# Replace the USERNAME_SMTP value with your Email Delivery SMTP username.
USERNAME_SMTP = 'my_smtp_credential_username'
 
# Put the PASSWORD value from your Email Delivery SMTP password into the following file.
PASSWORD_SMTP_FILE = 'ociemail.config'
 
# If you’re using Email Delivery in a different region, replace the HOST value with an appropriate SMTP endpoint.
# Use port 25 or 587 to connect to the SMTP endpoint.
HOST = "smtp.us-ashburn-1.oraclecloud.com"
PORT = 587
 
# The subject line of the email.
SUBJECT = 'Email Delivery Blog Test'
 
# The email body for recipients with non-HTML email clients.
BODY_TEXT = (
             "This email was sent through the Email Delivery SMTP "
             "Interface using the Python smtplib package."
            )
 
# get the password from a named config file ociemail.config
with open(PASSWORD_SMTP_FILE) as f:
    password_smtp = f.readline().strip()

# create message container
msg = EmailMessage()
msg['Subject'] = SUBJECT
msg['From'] = email.utils.formataddr((SENDERNAME, SENDER))
msg['To'] = RECIPIENT

# make the message multi-part alternative, making the content the first part
msg.add_alternative(BODY_TEXT, subtype='text')

# Try to send the message.
try: 
    server = smtplib.SMTP(HOST, PORT)
    server.ehlo()
    # most python runtimes default to a set of trusted public CAs that will include the CA used by OCI Email Delivery.
    # However, on platforms lacking that default (or with an outdated set of CAs), customers may need to provide a capath that includes our public CA.
    server.starttls(context=ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH, cafile=None, capath=None))
    # smtplib docs recommend calling ehlo() before & after starttls()
    server.ehlo()
    server.login(USERNAME_SMTP, password_smtp)
    # our requirement is that SENDER is the same as From address set previously
    server.sendmail(SENDER, RECIPIENT, msg.as_string())
    server.close()
# Display an error message if something goes wrong.
except Exception as e:
    print(f"Error: {e}")
else:
    print("Email successfully sent!")

In the same directory, I created a file named ociemail.config that contains my SMTP credential password. To run the script, use the following command:

python3 ociemail.py


Figure 14: Running script


FIgure 15: Email received

Suppression list

Under Email Delivery, you can also see Suppression List. This list includes emails that Email Delivery doesn’t send any messages to. As you begin to send email, Email Delivery automatically adds email addresses with bounce codes showing permanent failures or user complaints to the suppression list to protect your sender reputation. To manually add email addresses to your suppression list, click Add Suppression.

Volume testing

To maintain both your sender reputation and ours, use the following best practices in testing at volume:

  • Use a receipt address at the email-blackhole.com domain, such as example@email-blackhole.com. Email Delivery accepts the mail but doesn’t deliver it to an inbox.

  • If large volume emails are sent to valid email addresses, receivers reject them, resulting in many hard bounces. This result negatively affects IP reputation. For testing bounce processing, send small amounts of emails to a domain that doesn’t exist.

Conclusion

OCI Email Delivery is an out-of-the-box, developer-friendly service that solves configuration, infrastructure, security, and authentication issues for email delivery. Email Delivery ensures that emails reach user inboxes as you scale the number and frequency of outbound emails, which is critical for any business communicating with their customers. This service exists in all OCI regions and realms and is ideal for transaction, application-generated emails. We saw how easy it is to configure our email domain and approved sender and used a simple Python script to test everything. For more information and examples, refer to the official documentation.

Oracle Cloud Infrastructure provides Enterprise features for developers to build modern cloud applications. If you want to try out this blog for free, I recommend the Oracle Cloud Free Tier with US$300 credits for a 30-day free trial. Free Tier also includes several “Always Free” services that are available for an unlimited time, even after your free credits expire.

Cody Brinkman

Cloud Architect

Cody is a Cloud Architect for Oracle Cloud's Commercial accounts


Previous Post

Creating, Building, and Invoking a Function on OCI with Terraform

Lucas Jellema | 6 min read

Next Post


Announcing OCI Vision service

Kate D'Orazio | 5 min read