Sending email in common-lisp
+ +Summary:
++This page covers how to send an email from your common-lisp coding using the cl-smtp library using googles gmail servers. +
+Introduction
++This post covers a working example on how to send email from the common-lisp (cl) language using googles servers. The provided +example has been tested as an individual, and regularly used from the 'google workspace' account. +
+Requirements:
++An Application password. +
+ ++Google detailed getting one here. One fact that was missed is that you now need 2FA +configured for the account or you can not make app passwords. +
+Ideas for improvement.
+1. Secret Storage mechanism.
++The application password needs to be stored somewhere, my advice is not to have it stored in plaintext. +
+ ++If your application is hosted on a containerized platform, you can pass it as environment variables, or +some of them have secrets file. +
+2. Preventing secret leaks.
++After the secret is loaded into memory, destroy the file or environment setting so it is harder for attackers +to abuse the information. +
+ +(setf (uiop:getenv "SOME_ENVIRONMENT_VARIABLE") "PASSWORD-REMOVED-FOR-SECURITY-REASONS") ++
+When it is loaded, use Secret Values which will prevent passwords appearing in backtraces or logs. +
+3. Preventing accidental/intention spamming.
++Your application may accidentally send out hundreds of mail if a function is run repeatedly accidentally. +It is important that the program keep an accurate, reliable mechanism to know when a limits are abused. +
+The code:
++Listed below is the common-lisp code that is required to send email. The "password" is stored +in the environment variable GMAIL_KEY, as a single string. Google often displays on the 'app password' +page as 4 sets of 4 characters, aka xxxx xxxx xxxx xxxx , however experience shows that there was no space required. +
+ ++(ql:quickload "cl-smtp") +(ql:quickload "cl-mime") + +(defun email-report (&key to cc subject html) + "Generic send SMTP mail with some TEXT to RECIEPIENTS" + (let ((from "your@gmail.com") + (login "youraccount@gmail.com") + (passwd (uiop:getenv "GMAIL_KEY"))) + + (cl-smtp:with-smtp-mail (out "smtp.gmail.com" to cc + :ssl :tls + :authentication `(,login ,passwd)) + + (format out "To: ~A~%" to ) + (format out "Subject: ~A~%" subject) + + (cl-mime:print-mime out (make-instance 'cl-mime:mime + :type "text" :subtype "html" + :encoding :base64 + :content html) t t)))) + +(devar html-mail-content "<html><h1> THis is html, but not really. </h1></html>") + +(email-report :to "someone@example.com" + :cc *cc-list* + :subject email-subject + :html html-content) ++
Conclusion
++This example works for both personal and google workspace accounts. +
+