Automating email sending with SwiftSMTP and launchd

I am unhappy with my email sending automation using AppleScript and the Apple Calendar App. I have been searching for a better solution for quite some time. Sending emails is a complicated problem in 2022 :-).

Yesterday I finally found a solution that worked—using the SwiftSMTP library from https://github.com/Kitura/Swift-SMTP, in conjunction with a simple launchd file.

The swift code

Thanks to the library, the code to send my email is straightforward. And please keep in mind that this is an example. Don’t save your passwords in the code in a real app (and don’t commit them to git).

import Foundation
import SwiftSMTP

let smtp = SMTP(
    hostname: "smtp.gmail.com",     // SMTP server address
    email: "",                      // email address
    password: ""                    // password / app password
)

let from = Mail.User(name: "AutoMailer", email: "info@example.com")
let to = Mail.User(name: "Chris", email: "info@example.com")

let inputFormatter = DateFormatter()
inputFormatter.dateFormat = "yyyy-MM-dd"
let dateString = inputFormatter.string(from: Date())

let mail = Mail(
    from: from,
    to: [to],
    subject: "Done list for \(dateString)",
    text: "What have you done so far?"
)

smtp.send(mail) { (error) in
    if let error = error {
        print(error)
        exit(EXIT_FAILURE)
    }
    
    print("Sending mail is done")
    exit(EXIT_SUCCESS)
}

dispatchMain()

The last line will block the main thread, preventing the application from exiting before the mail sending is done. We then explicitly quit the application in the callback to end the process.

Using Gmail for sending

On my first try, I got a warning from Gmail (Critical security alert) that an unsafe client tried to log in to my account: Sign-in attempt was blocked. I did not find out the reason for this warning, but there are two options you have to solve it. The first is activating the “less secure app” option in the Google Account Settings panel. But this is not recommended! I went for the second option to generate an app password for my auto mailer. You need to have two-factor auth enabled to use the app passwords option.

Setting up the launchd service

Creating the service is relatively simple at this point. You need a plist file describing it.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
"http://www.apple.
com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>  
    <key>Label</key>
    <string>ch.vmac.done-list</string>
    <key>Program</key>
    <string>/Users/chris/AutoMailer</string>
    <key>StartCalendarInterval</key>
    <dict>  
        <key>Hour</key>
        <integer>4</integer>
        <key>Minute</key>
        <integer>1</integer>
    </dict>
</dict>
</plist>

The file needs to be saved in ~/Library/LaunchAgents/ under the following name: ch.vmac.doneList.plist. Then you load the new service with:

> launchctl load ~/Library/LaunchAgents/ch.vmac.doneList.plist

I’ve had some success with seeing errors for the service by using the following command (in a second terminal window):

> tail -F /var/log/system.log

I had issues with the Program key at first and got an error 78 back from the service:

> launchctl list | grep vmac
-  78  ch.vmac.done-list

This was due to my program path containing spaces. You can escape spaces with a backslash, but I did not get this to work. So I just copied my app to another location.

I found the following homepage https://www.launchd.info quite helpful. When everything works, the service runs every day at 4:01 in the morning.

Comments

How to respond

Write your comment on your on page and link it to this page with the following link:
https://vmac.ch/posts/2022-01-02-automating-email-sending/
Then insert the permalink to your post into the form below and submit it.

Alternatively you can reach me by email to: comment@vmac.ch