How to compose and send customized emails to a list of recipients
using Perl and Mail::Message.
Yesterday I made an invitation to a concert and sent it to a longish list of friends. To that end I made a table with the needed fields for each correspondent and a program similar to the following. I post them here for my own reference, but they may prove useful to someone else.
#+name: list
| formal | name | emails | Intro | custom | Extra |
|---|---|---|---|---|---|
| A Very Long Name | Shorty | <s@one>, <s@two> | Hi | something | 1 |
| Prof. First Second Last | Last | <last@address> | Dear Prof. | anything |
#+name: invite
#+begin_src perl -n :results output :var list=list
1 use v5.36;
2 use Mail::Message;
3 use Encode;
4 my $count=0;
5 my $time=0;
6 for($list->@*){
7 my ($formal, $short, $emails, $intro, $custom, $extra)=@$_;
8 my $to = "$formal $emails";
9 my $extra_text=$extra?"You can selectively interpolate additional text\n":"";
10 my $body = decode("UTF8", <<~"END");
11 $Intro $name,
12 This is the main text of the email, in which I can interpolate $custom.
13 $extra_text
14 Regards,
15 Myself
16 Attachment: Some image
17 END
18
19 my $msg = Mail::Message->build(
20 From => 'My Name <my@address>',
21 To => $to,
22 Subject => 'Subject',
23 data => $body,
24 file => "$ENV{HOME}/path/to/image.png"
25 );
26 $msg->send;
27 my $delta_t=1+ rand(1);
28 sleep $delta_t;
29 $time += $delta_t;
30 ++$count;
31 say "$count $time $formal";
32 }
I use the var mechanism of emacs’ org-mode to import the table as
a nested array reference into the program. For each line I make a
customized email. Notice that in order to attach a file such as an
image it is enough to include a line like 24. I asked chatgpt about
adding attachments to Mail::Message objects. I got several
contradictory and wrong answers, but I finally read the
manual. Mail::Message figures out all the mime magick. Furthermore,
I used decode from Encode in order to use UTF-8 characters such as
accented characters in the body of the message. It seems not to be
necessary for the names of the recipients nor the sender. I added some
random sleep time after each message (lines 27 and 28), actually, much
longer than shown here, in order not to abuse the network and not to
appear to be a spammer.