A few months ago I wrote about various tricks for sending email/text messages from Matlab. Unfortunately, Matlab only sends text emails by default and provides no documented way to send HTML-formatted emails. Text-only emails are naturally very bland and all mail clients in the past 2 decades support HTML-formatted emails. Today I will show how we can send such HTML emails from Matlab.
A quick recap: Matlab’s sendmail function uses Java (specifically, the standard
javax.mail package) to prepare and send emails. The Java classes are extremely powerful and so there is no wonder that Mathworks chose to use them rather than reinventing the wheel. However, Matlab’s sendmail function only uses part of the functionality exposed by these classes (admittedly, the most important parts that deal with the basic mail-sending mechanism), and does not expose external hooks or input args that would enable the user to take full advantage of the more advanced features, HTML formatting included.
Only two small changes are needed in sendmail.m to support HTML formatting:
- HTML formatting required calling the message-object’s setContent() method, rather than setText().
- We need to specify
'text/html'as part of the message’s encoding
To implement these features, change the following (lines #119-130 in the original sendmail.m file of R2017a, changed lines highlighted):
% Construct the body of the message and attachments. body = formatText(theMessage); if numel(attachments) == 0 if ~isempty(charset) msg.setText(body, charset); else msg.setText(body); end else % Add body text. messageBodyPart = MimeBodyPart; if ~isempty(charset) messageBodyPart.setText(body, charset); ...
to this (changed lines highlighted):
% Construct the body of the message and attachments. body = formatText(theMessage); isHtml = ~isempty(body) && body(1) == '<'; % msg starting with '<' indicates HTMLif isHtml if isempty(charset) charset = 'text/html; charset=utf-8'; else charset = ['text/html; charset=' charset]; endendif numel(attachments) == 0 && ~isHtml if isHtml msg.setContent(body, charset); elseif ~isempty(charset) msg.setText(body, charset); else msg.setText(body); end else % Add body text. messageBodyPart = MimeBodyPart; if isHtml messageBodyPart.setContent(body, charset); elseif ~isempty(charset) messageBodyPart.setText(body, charset); ...
In addition, I also found it useful to remove the hard-coded 75-character line-wrapping in text messages. This can be done by changing the following (line #291 in the original sendmail.m file of R2017a):
maxLineLength = 75;
maxLineLength = inf; % or some other large numeric value
It’s useful to note two alternatives for making these fixes:
- Making the changes directly in %matlabroot%/toolbox/matlab/iofun/sendmail.m. You will need administrator rights to edit this file. You will also need to redo the fix whenever you install Matlab, either installation on a different machine, or installing a new Matlab release. In general, I discourage changing Matlab’s internal files because it is simply not very maintainable.
- Copying %matlabroot%/toolbox/matlab/iofun/sendmail.m into a dedicated wrapper function (e.g., sendEmail.m) that has a similar function signature and exists on the Matlab path. This has the benefit of working on multiple Matlab releases, and being copied along with the rest of our m-files when we install our Matlab program on a different computer. The downside is that our wrapper function will be stuck with the version of sendmail.m that we copied into it, and we’d lose any possible improvements that Mathworks may implement in future Matlab releases.
The basic idea for the second alternative, the sendEmail.m wrapper, is something like this (the top highlighted lines are the additions made to the original sendmail.m, with everything placed in sendEmail.m on the Matlab path):
function sendEmail(to,subject,theMessage,attachments)%SENDEMAIL Send e-mail wrapper (with HTML formatting) sendmail(to,subject,theMessage,attachments); % The rest of this file is copied from %matlabroot%/toolbox/matlab/iofun/sendmail.m (with the modifications mentioned above): function sendmail(to,subject,theMessage,attachments) %SENDMAIL Send e-mail. % SENDMAIL(TO,SUBJECT,MESSAGE,ATTACHMENTS) sends an e-mail. TO is either a % character vector specifying a single address, or a cell array of character vector ...
We would then call the wrapper function as follows:
sendEmail('email@example.com', 'email subject', 'regular text message'); % will send a regular text message sendEmail('firstname.lastname@example.org', 'email subject', '<b><font color="blue">HTML-formatted</font> <i>message'); % HTML-formatted message
In this case, the code automatically infers HTML formatting based on whether the first character in the message body is a ‘<‘ character. Instead, we could just as easily have passed an additional input argument (
isHtml) to our sendEmail wrapper function.
Hopefully, in some future Matlab release Mathworks will be kind enough to enable sending 21st-century HTML-formatted emails without needing such hacks. Until then, note that sendmail.m relies on standard non-GUI Java networking classes, which are expected to be supported far into the future, well after Java-based GUI may cease to be supported in Matlab. For this reason I believe that while it seems a bit tricky, the changes that I outlined in today’s post actually have a low risk of breaking in a future Matlab release.
Do you have some other advanced email feature that you use in your Matlab program by some crafty customization to sendmail? If so, please share it in a comment below.