19
$\begingroup$

I want Mathematica to send me an email when the computation is finished. To that end, I have a cell with SendMail[...] which I place behind my computation in the evaluation queue. The problem I have is that I need to enter a password for my mail server. Doing that as an explicit rule leaves the password unencrypted and visible to everyone. On the other hand, setting "Password" -> Automatic will only show a dialog box once the SendMail[] cell is evaluated. Is there a way to show the dialog box for password entry beforehand, such that I can enter the password and walk away?

$\endgroup$
1
  • $\begingroup$ DialogInput? See first example in section "Scope". Mind you, as long as your machine is not locked, retrieving the password will still be trivial... $\endgroup$
    – Yves Klett
    Commented Aug 21, 2013 at 11:03

2 Answers 2

7
$\begingroup$

In general SendMail should not access an email account that stores important emails or that functions to reset the passwords of other online accounts. Such a valuable email account should be protected by two-factor authentication as well as user-managed access such as OAuth, and so forth. Because SendMail does not support any such features it can not access an truly secure email account. Rather than accept inadequate security on an important email account, it is much better to setup a separate email account especially for SendMail to access. If this special account is on gmail, then SendMail will require the Allow less secure apps setting. In addition, because it will only be used with SendMail the need to encrypt its password will depend solely the SendMail application’s security needs.

Besides setting up an email account especially for SendMail, there are at least two other email solutions to consider.

If you’re developing web applications, then you may already be using the free version of the Wolfram Development Platform. If you’re not at least at the $20/month Explorer plan, then upgrade and you will be able to deploy and call a SendMail API in the Wolfram Cloud:

CloudDeploy[
   APIFunction[
      {  "To" -> <|"Interpreter" -> "EmailAddress"|>,
         "Subject" -> "String",
         "Body" -> "String" },
      SendMail[#] &], 
   FileNameJoin[{$CloudRootDirectory, "WolframCloudSandboxEmail"}],
   Permissions -> "Public" ]

You only need to do the above CloudDeploy once. Then every time you want to send an email, just call the API from your desktop:

URLExecute[
   FileNameJoin[{$CloudRootDirectory, "WolframCloudSandboxEmail"}],
   {  "To" -> "YOUR-NAME <YOUR-EMAIL-ADDRESS>", 
      "Subject" -> "Wolfram Cloud Sandbox Email", 
      "Body" -> "Here is the body of the message." } ]

If for some reason you don’t want a public API that sends you email, then deploy the API as a private cloud object, add the Username and Password options to URLExecute, and protect it by the encoded package approach in Murta’s answer:

URLExecute[
   FileNameJoin[{$CloudRootDirectory, "WolframCloudPrivateSandboxEmail"}],
   {  "To" -> "YOUR-NAME <YOUR-EMAIL-ADDRESS>", 
      "Subject" -> "Wolfram Cloud Private Object Sandbox Email", 
      "Body" -> "Here is the body of the message." }, 
   "Username" -> "YOUR-WOLFRAM-ID",
   "Password" -> "YOUR-WOLFRAM-CLOUD-PASSWORD" ]

On the other hand, if you’re developing applications that have the potential to generate a significant volume of email, you probably are already using or at least considering an email delivery service. Calling such a service will be among your standard approaches to sending an email. For example, you can easily setup and use a Mailgun sandbox:

URLFetch["https://api.mailgun.net/v3/YOUR-SANDBOX-DOMAIN-NAME/messages",
   "Method" -> "POST",
   "MultipartElements" ->
      {  {"from", "text/plain"} ->
            "Mailgun Sandbox <postmaster@YOUR-SANDBOX-DOMAIN-NAME>",
         {"to", "text/plain"} -> "YOUR-NAME <YOUR-EMAIL-ADDRESS>",
         {"subject", "text/plain"} -> "Mailgun Sandbox Email",
         {"text", "text/plain"} -> "Here is the body of the message." },
   "Username" -> "api",
   "Password" -> "YOUR-PRIVATE-API-KEY"]

Assuming that the mail delivery service is also being used to send other important emails, then its password could again be protected by the approach in Murta’s answer.

Comment 2/9/16:

As originally posted this answer simply alerted readers to the email delivery service alternative to SendMail and left it to them to decide on its suitablity for their application. This updated answer adds a Wolfram Development Platform alternative and specifies circumstances that might favor each solution.

$\endgroup$
21
$\begingroup$

Here is one solution based on encoded package.

To create a pack you have to create a .m file (in this case mailPack.m). There is one example using gmail configuration:

BeginPackage["mailPack`"]

sendMail::usage="sendMail[subject, body, to, file] send mail using myMail";
Begin["`Private`"]

sendMail[subject_,body_,to_,file_:None]:=
SendMail[
    "To"->to,
    "Subject"->subject,
    "Body"->body,
    "From"->"[email protected]",
    "Server"->"smtp.gmail.com",
    "PortNumber"->587,
    "EncryptionProtocol"->"StartTLS",
    "UserName"->"myLogin",
    "Password"->Uncompress@"myCompressedPassword", (*Use compress to create it*)
    "Attachments"->file
]

SetAttributes[sendMail, {ReadProtected,Locked}];

End[]
EndPackage[]

Now you can open another notebook, save in the same directory, and the do this to encode the first:

  SetDirectory@NotebookDirectory[];
  Encode["mailPack.m","mailPack.m"];

Now, if you try to open your mailPack.m as txt file, you will see that it is completely unreadable.

To use your sendMailfunction, copy your pack in the same directory of your file, then use SetDirectory@NotebookDirectory[], then use Needs["mailPack"]. If you use it all the time, copy the mailPack.m for the Application directory in your Mathematica folder (this command can help you SystemOpen@$UserBaseDirectory). Then you don't need the SetDirectory part neither to put the mailPack file in the same directory of your current notebook.

$\endgroup$
7
  • 1
    $\begingroup$ Related: mathematica.stackexchange.com/questions/1571/… $\endgroup$
    – Yves Klett
    Commented Aug 21, 2013 at 11:18
  • $\begingroup$ Interesting that @Leonid suggest DumpSave instead of Encode. Also related about security of encode here. $\endgroup$
    – Murta
    Commented Aug 21, 2013 at 11:22
  • $\begingroup$ The juicy part is @RolfMertig´s comment on Locked in pre-9 versions... perhaps there is some more secure stuff possible via Java or similar? $\endgroup$
    – Yves Klett
    Commented Aug 21, 2013 at 11:25
  • 2
    $\begingroup$ This way it's more comfortable to open the code in front of another person, and if he is not Sheldon Cooper (with his eidetic memory) there is no problem. $\endgroup$
    – Murta
    Commented Aug 21, 2013 at 12:02
  • 1
    $\begingroup$ If you would store the compressed string in a file and read it from there, you could even share the notebook freely and the password wouldn't exist anywhere in plain text. You could also add a "salt" to your encryption. E.g. Compress["flsdjflfjks"<>pass<><>pass<>"tisisodjfdosij9294239"]. This way if someone has access to your computer, they cannot peak at the password by simply calling Uncompress. They'd have to look up the salt as well, which you could store somewhere else. $\endgroup$
    – C. E.
    Commented Aug 22, 2013 at 7:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.