Sending Email Using mailx/s-nail in Linux Through Gmail SMTP

The heirloom mailx (or s-nail if you are using Ubuntu 18 or later or similar releases) command in Linux is still providing service for guys like me, especially when we need to send email automatically by script. Gmail is great. Now, how to use gmail’s smtp in mailx/mail? gmail is a little special since gmail’s smtp server requires tls authorization. The good news is that mailx supports it. Let’s look at how to use it.

There are two ways to do this: using all-in-one command or putting configurations into profile. The all-in-one-command way needs no other configurations except the command line itself, while the way using configuration has a clearer command.

All-in-one command

mailx accepts most configuration in the command line directly from the -S options in format -S variable[=value] (check more in mailx manual).

Sets the internal option variable and, in case of a string option, assigns value to it. Note, that when setting from variable, domain name of host is automatically added if value does not contain any. If you want to enter from address with owner’s name, you can use, for example, following format: -S “from=System User

This is an all-in-one command that sends email to $TO_EMAIL_ADDRESS

(use `s-nail` instead in releases without the heirloom mailx)

$ mailx -v -s "$EMAIL_SUBJECT" \
-S smtp-use-starttls \
-S ssl-verify=ignore \
-S smtp-auth=login \
-S smtp=smtp://smtp.gmail.com:587 \
-S from="$FROM_EMAIL_ADDRESS($FRIENDLY_NAME)" \
-S smtp-auth-user=$FROM_EMAIL_ADDRESS \
-S smtp-auth-password=$EMAIL_ACCOUNT_PASSWORD \
-S ssl-verify=ignore \
$TO_EMAIL_ADDRESS

Replace the `$…` above with the value that is actually used.

This command will ask for the email content. Type in the mail content and after finishing the email, use “Ctrl+d” to tell mailx you have finished. Then this mail will be sent out through gmail’s smtp server. You can also use pipe like this:

echo "The mail content" | mailx -v -s ...

Security notes on passwords

  • you may consider not setting -S smtp-auth-password and input it each time you use this command. Passwords in the command line can be seen by other users on the system.
  • Gmail now supports “App Password” if you are using Google’s 2-Step verification and you will need to use it instead of your Gmail’s password. You can generate an “App Password” for mailx so it can be easily revoked in case it leaked out. Go to this URL: https://myaccount.google.com/apppasswords . Click on “Select App” → “Other”, type “mailx”, and hit “Generate”. You will get a password used by mailx. (thanks to Ben for the notes).

About nssdb used by mailx

Most Linux system’s default nssdb should be already updated so that gmail is good with it. But if your system does not have an updated nssdb, you may consider using Firefox’s instead by adding such option

-S nss-config-dir=~/.mozilla/firefox/yyyyyyyy.default/

Find out Firefox’s profile directory in the home directory which commonly has a format like this:

~/.mozilla/firefox/yyyyyyyy.default

yyyyyyyy is a random string that’s different for different users. You can easily find it out by looking into the directory ~/.mozilla/firefox.

Use mailx configuration file

There are too many options in the above command? Yes… I must confess so. We can write most of them into mailx/mail’s configuration file ~/.mailrc

set smtp-use-starttls
set ssl-verify=ignore
set smtp=smtp://smtp.gmail.com:587
set smtp-auth=login
set smtp-auth-user=$FROM_EMAIL_ADDRESS
set smtp-auth-password=$EMAIL_ACCOUNT_PASSWORD
set from="$FROM_EMAIL_ADDRESS($FRIENDLY_NAME)"

For better security, you may set the mode of ~/.mailrc to 600 by chmod 600 ~/.mailrc.

The variables set are the same as those used in the “all in one command”.

When sending mails, use this command:

$ mailx -v -s "$EMAIL_SUBJECT" $TO_EMAIL_ADDRESS

Or

$ echo "The mail content" | mail -v -s "$EMAIL_SUBJECT" $TO_EMAIL_ADDRESS

Then, time to enjoy it!

Eric Ma

Eric is a systems guy. Eric is interested in building high-performance and scalable distributed systems and related technologies. The views or opinions expressed here are solely Eric's own and do not necessarily represent those of any third parties.

62 comments:

  1. Fedora 13 has a system directory for the network security services (NSS) files.
    nss-config-dir=/etc/pki/nssdb/

    Ubuntu 10.4 doesn’t seem to have a system directory for NSS files.

  2. Hi Adam,

    Yes. Some systems do not have the /etc/pki/nssdb/ directory. As far as I now, the nss files in Fedora do not work well with gmail.

    So we use Firefox’s version of these nss files which supports gmail quite well.

  3. This was very helpful but why the requirement of the ‘set nss-config-dir=~/.mozilla/firefox/xxxxxxxx.default/’ variable. What is it’s purpose, it seems to work perfectly without it.

    Jim!

  4. @Jim!
    In my Linux box (Fedora 12, mailx -V: 12.4 7/29/08). mailx doesn’t work without ‘set nss-config-dir=…’. I think it depends on the default mailx configuration file (/etc/mail.rc) which may different on different Linux distros. I look into the mail.rc file in my system, there is no ‘nss-config-dir’ configuration. So I need to set it in ~/.mailrc

    In my system, there is a directory /etc/pki/nssdb which can also be used as ‘nss-config-dir’. It works while we get a error message every time:
    Error in certificate: Peer’s certificate issuer is not recognized.

    Only firefox’s directory works perfectly from my experiment. As I have pointed out, it may also work without setting it.

  5. Hey there, I’m sending from a sidux (debian sid) laptop and edited the /etc/nail.rc file (mailx formerly called nail) then symlinked to /etc/mail.rc. File didn’t exist but that may be due to my ensuring sendmail/postfix/etc. were purged from my system.

    Once I my server back up and working (Fedora 12/Amahi)‘set nss-config-dir=~/.mozilla/firefox/xxxxxxxx.default/’ may be of use.

    BTW you’re original article is concise and to the point unlike others I came across so thank you.

    Jim!

    1. That’s strange. I find from Ubuntu’s site the mailx has -S option. Please try again and check whether the package you are using is right.

      1. we find answer. two mailx exists. heirloom-mailx have -S option, but mailutil’s mailx haven’t :)

  6. I could not find the firefox’s profile directory.. I would be really grateful if someone would help me out…

    1. It is usually under ~/.mozilla/firefox with a name xxxxxxxx.default .

      If you never run Firefox before, this directory may not exist. You can install it and run it once, then the directory should be there.

  7. I am having some problems. The following message comes on the terminal.
    Anyone knows what can be the problem. Does this “mail” command use system proxy settings on its own or i need to set it. Thanks in advance.

    Connecting to 173.194.79.108:587 . . .Connecting to 173.194.79.109:587 . . .could not connect: Connection timed out
    “/home/agam/dead.letter” 12/357
    . . . message not sent.

    1. Some command line tools accept proxy setting via environmental variables:

      export http_proxy=http://IP:PORT

      and

      proxy_username=USERNAME
      proxy_password=PASSWORD

      if username:password is needed.

      I am not sure mailx accepts these variables. But it may worth a try.

      1. It didn’t work. It does look like mailx doesn’t work with proxy. Anyway, thanks for the reply.

  8. Thanks, this is great stuff.
    Having done your setup with putting settings in ~/.mailrc on RHEL5.8, I’m trying this:
    #cat ~/mailbody.txt | sendmail -s “SUBJECT” -fmail@domain.com mail@domain.com
    I’m using sendmail as I can change the ctladdr/from-address to something else instead of USER@LOCALHOST which allows recipients to reply to the mail.
    I had this working for a short time, but now sendmail seems to parse the command arguments incorrectly. If I add -s “SUBJECT” sendmail will treat SUBJECT, -fmail@domain.com and mail@domain.com as recipients all… If I leave out -s “SUBJECT” it will parse the remaining arguments correctly, but with no subject mails are treated as spam.
    Any ideas?
    Thanks

    1. Hi TAG,

      From: http://www.sendmail.org/~ca/email/man/sendmail.html

      Sendmail is not intended as a user interface routine; other programs pro-
      vide user-friendly front ends; sendmail is used only to deliver pre-for-
      matted messages.

      I am not sure the `sendmail` command you are using will read the configuration from ‘~/.mailrc’.

      I suggest using `mailx` directly. The manual:

      https://www.systutorials.com/docs/linux/man/1-heirloom-mailx/.

      For your command, the `mailx` version may be:

      mailx -s “SUBJECT” -r mail@domain.com mail@domain.com

      1. Thanks for your reply.

        Well, if I pass -r I get mailx: invalid option — r

        I already looked into man mailx to see if mailx would do this, and found that it didn’t. That’s why I tried sendmail. Using sendmail works – I can send mails this way – it’s just that when using -s it does as descirbed in previous post.

        rpm -qa | grep mailx
        mailx-8.1.1-44.2.2

        rpm -qa |grep sendmail
        sendmail-8.13.8.8.el5

        Maybe I need a different version of mailx? This is the one out-of-the-box on RHEL5.8.

        Thanks.

        1. Ah.. my fault. You are using an older version of `mailx`. On my box, the mailx is:

          mailx-12.5-6.fc17.x86_64

          If updating mailx is possible, after installing a newer version of it, you should be able to use ‘-r’.

          1. Well, you couldn’t what version I had running… Thanks, but 8.1.1-44.2.2 seems to be it for RHEL5… RHEL6 has mailx-12 ootb, but I’m stuck with RHEL5 on the box in question for now.
            Might have to let the script run on some other machine with mailx-12, then, and have it ssh into the other box for the non-mail-stuff it needs to do there… Just seems a little foolish to have to build and extra machine for that purpose alone…

              1. Thanks, but I don’t know anything about building. Just tested on a FC14 box. Works like a charm, except for a certificate issuer warning even though I specified nss location as the sending users firefox xxxxxx.default file… The prompt sort of hangs after that, so that might be an issue when scripting. I haven’t started on the actual script yet, as I wanted to get mailing to work first. Did not give warning on RHEL5.8…

  9. Nice tip; working great for me. Thank you! Wish I’d found this 2 years ago when I first tried it; the guide I used did not mention the nss-config-dir parameter, and leaving that out causes authentication errors (think it was MX validation stuff). I believe it worked without that at one time, but not for several years now.

  10. I got a PHP Mail Sender but I want it to use random proxy for sending emails.

    I have API for the proxy

    Change mail.php:

    (TESTEMAIL@HOTMAIL-YOU-CAN-ADD-YOUR-OWN-TEST-EMAIL-HERE.COM)

    To email you want to receive test emails.

  11. Notice that mailx has different alternatives. For me this works when using heirloom-mailx but mail.mailutils fails, it does not know the -v switch.

  12. I ‘m having difficulty sending mail.
    My mail.rc is below account gmail {
    set smtp-use-starttls
    set ssl-verify=ignore
    set smtp-auth=login
    set smtp=smtp://smtp.gmail.com:587
    set from=”email@gmail.com”
    set smtp-auth-user=uname
    set smtp-auth-password=***********
    set ssl-verify=ignore
    set nss-config-dir=/etc/pki/nssdb/
    }

    But I’m getting error
    [root@localhost ~]# echo -e “Mail body text” | mailx -A gmail -s “Mail subject” uname.example.com
    [root@localhost ~]# Error in certificate: Peer’s certificate issuer is not recognized.
    smtp-server: 534-5.7.14 Please log in via your web browser and
    smtp-server: 534-5.7.14 then try again.
    smtp-server: 534-5.7.14 Learn more at
    smtp-server: 534 5.7.14 https://support.google.com/mail/answer/78754 205sm11220769pfy.32 – gsmtp
    “/root/dead.letter” 11/337
    . . . message not sent.

    I think I’m having a certificate issue. I used the firefox certificates also. Still same issue.

    I’m using RHEL7 .

    Could you please help me

  13. I ‘m having difficulty sending mail.
    My mail.rc file is below

    account gmail {
    set smtp-use-starttls
    set ssl-verify=ignore
    set smtp-auth=login
    set smtp=smtp://smtp.gmail.com:587
    set from=”email@gmail.com”
    set smtp-auth-user=uname
    set smtp-auth-password=***********
    set ssl-verify=ignore
    set nss-config-dir=/etc/pki/nssdb/
    }

    But I’m getting error
    [root@localhost ~]# echo -e “Mail body text” | mailx -A gmail -s “Mail subject” uname.example.com
    [root@localhost ~]# Error in certificate: Peer’s certificate issuer is not recognized.
    smtp-server: 534-5.7.14 Please log in via your web browser and
    smtp-server: 534-5.7.14 then try again.
    smtp-server: 534-5.7.14 Learn more at
    smtp-server: 534 5.7.14 https://support.google.com/mail/answer/78754 205sm11220769pfy.32 – gsmtp
    “/root/dead.letter” 11/337
    . . . message not sent.

    I think I’m having a certificate issue. I used the firefox certificates also. Still same issue.

    I’m using RHEL7 .

    Could you please help me

    1. The link in the gmail smtp’s message provides some information:

      – Visit http://www.google.com/accounts/DisplayUnlockCaptcha and sign in with your Gmail username and password. If asked, enter the letters in the distorted picture.
      – Your app might not support the latest security standards. Try changing a few settings to allow less secure apps access to your account https://support.google.com/accounts/answer/6010255 .

      You may try these steps and try again.

  14. I’ve done all this (heirloom mailx on mac OS X) and everything works fine — except that on issuing the mailx command i’m still asked for my gmail password every time, even though password is specified with “set smtp-auth-password” in the .mailrc file as above. it would be really nice to make this automatic. any idea what i might need to fix?

    1. I haven’t a mac OS X by hand and can’t try. But some potential problems to check:

      – does your password contain some special characters like ‘@’, ‘$’? You may try use a password with only plain characters.
      – I am not sure whether the heirloom mailx version you are using disabled the smtp-auth-password or not. You may check the release doc of that build for mac OS X.

      You may also print the STDOUT content so that others can check whether there are some clues.

  15. Thanks! The problem persists even when I get rid of special characters. I couldn’t find any documentation of disabled smtp-auth-password. The heirloom version I’m using is the Mac OS X port for which there’s a link (now dead) on http://heirloom.sourceforge.net/. Here’s verbose output:

    Resolving host imap.gmail.com . . . done.
    Connecting to 173.194.66.109:993 . . . connected.
    * OK Gimap ready for requests from 173.68.122.183 [characters[
    >>> T1 CAPABILITY
    * CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XO\
    AUTH2 AUTH=PLAIN AUTH=PLAIN-CLIENTTOKEN AUTH=OAUTHBEARER AUTH=XOAUTH
    T1 OK Thats all she wrote! [characters]
    Password:
    >>> T2 LOGIN “username” “password” [this one always reflects the entered password]
    * CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 UIDPLUS COMPRESS=DEFL\
    ATE ENABLE MOVE CONDSTORE ESEARCH UTF8=ACCEPT LIST-EXTENDED LIST-STATUS LITERAL- SPECIAL-USE APPENDLIMI\
    T=35651584
    T2 OK username authenticated (Success)
    >>> T3 SELECT “INBOX”
    * FLAGS (\Answered \Flagged \Draft \Deleted \Seen $NotPhishing $Phishing)
    * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen $NotPhishing $Phishing \*)] Flags permit\
    ted.
    * OK [UIDVALIDITY 649428526] UIDs valid.
    * 93 EXISTS
    * 0 RECENT
    * OK [UIDNEXT 78858] Predicted next UID.
    * OK [HIGHESTMODSEQ 9846256]
    T3 OK [READ-WRITE] INBOX selected. (Success)
    >>> T4 FETCH 1:93 (FLAGS UID)
    * 1 FETCH (UID 22587 FLAGS (\Seen))

    1. > Resolving host imap.gmail.com . . . done.
      > Connecting to 173.194.66.109:993 . . . connected.
      > * OK Gimap ready for requests from 173.68.122.183

      It seems you are using imap. The example in the post is about smtp.

      FYI, a SMTP connection’s output will be like this:

      Resolving host smtp.gmail.com . . . done.
      Connecting to 74.125.204.108:587 . . . connected.
      220 smtp.gmail.com ESMTP ...... - gsmtp

      Are you trying to receiving emails or sending emails? If your purpose is to use imap with `mailx`, you may check whether the `password-user@host` setting of `mailx` ( https://www.systutorials.com/docs/linux/man/1-mailx/ ) can work for you to set the imap account password (I didn’t test it).

      1. I’m both receiving using imap and sending using smtp, with code like the above for both imap and smtp in my .mailrc. I take your point that the password at issue is the imap password, not the smtp password (in fact I can send mail without being prompted for a password). Imap password is currently set with both “set imap-auth-password=” and with “set-password-user@host=” in .mailrc, but mailx still prompts for a password.

          1. Here’s the relevant part, with username and password changed to “username” and “passwd”. N.B. My main account is a google apps account. I’ve used a gmail account here for simplicity, since it displays the same behavior (though possibly some of the below is redundant for gmail).

            set folder=imaps://username@gmail.com@imap.gmail.com
            set MAIL=imaps://username@gmail.com@imap.gmail.com:993/INBOX
            set password-username@gmail.com@imap.gmail.com=passwd
            set-imap-use-starttls
            set imap-auth=login
            set imap-auth-user=username@gmail.com
            set imap-auth-password=passwd
            set imap-auth-password-username@gmail.com=passwd
            set imap-cache=~/imap
            
            set smtp-use-starttls
            set smtp=smtp://smtp.gmail.com:587
            set smtp-auth=login
            set smtp-auth-user="username@gmail.com"
            set smtp-auth-password="passwd"
            set smtp-auth-password-username@gmail.com="passwd"
            set from="username@gmail.com (Name)"
            set ssl-verify=ignore
            1. this is does NOT work for imap.
              I had to read heirloom-mailx’s code in order to understand that we should use either folder or MAIL, but not both. When folder exists, then MAIL is ignored.

  16. Hi Dave,

    Your mailrc config is almost correct. Here is a working one for your reference.

    set ssl-verify=ignore
    set nss-config-dir=~/.mozilla/firefox/YOUR_FIREFOX_DIR
    
    set folder=imaps://USERNAME@gmail.com@imap.gmail.com
    set MAIL=imaps://USERNAME@gmail.com@imap.gmail.com:993/INBOX
    set-imap-use-starttls
    set imap-auth=login
    set imap-auth-user=USERNAME@gmail.com
    set password-USERNAME@gmail.com@imap.gmail.com="PASSWORD"
    set imap-cache=~/imap
    
    set smtp-use-starttls
    set smtp=smtp://smtp.gmail.com:587
    set smtp-auth=login
    set smtp-auth-user="USERNAME@gmail.com"
    set smtp-auth-password="PASSWORD"
    set smtp-auth-password-USERNAME@gmail.com@gmail.com="PASSWORD"
    set from="USERNAME@gmail.com (Name)"
    

    The key is the variable:

    set password-USERNAME@gmail.com@imap.gmail.com="PASSWORD"
    1. Thanks! That looks essentially like what I have, including the key variable line. Are there any mistakes in my version that could have generated the password prompting? Changing to your version had the same result — unless I missed a change that I should be making.

      1. That’s quite strange and I have no idea what’s wrong any more. The version I gave is exactly the one I used for gmail with only the USERNAME, PASSWORD and YOUR_FIREFOX_DIR changed.

        You might try setting `nss-config-dir` as I noticed that you did not use it.

        1. OK, I’ve located the problem. Using your simple .mailrc without the rest of my (complicated) .mailrc worked without password prompt. I tested everything in the rest of my .mailrc and it turns out that deleting the following line removed the problem: set additionalfields=”. I don’t know why that is, but at least the practical problem is solved. Many thanks for your help, Eric!

          1. Actually, on closer look, the problem was generated by a second use of ‘set folder=’ later in .mailrc, used to specify a folder I can save messages to with the “+” method. Is there any way to set a folder for that purpose in addition to setting an imap folder on gmail?

  17. Dave wrote:

    […] a second use of ‘set folder=’ […] to specify a
    folder I can save messages to with the “+” method. Is
    there any way to set a folder for that purpose in
    addition to setting an imap folder on gmail?

    Hey Dave, You want to save messages in a file on your local machine? Why not use the copy (c) command to save them in ~/mbox? You can just hit ‘c’ for occasional messages, or you can specify a message list and folder name (e.g., ‘c :n mbox’ to save all new messages).

    1. thanks, ben! i have a complicated file system (going back decades) for saving different people’s emails to different files under different categories. i use a special folder (with “set folder=XX”) as the base folder for that, saying ‘s +person’ when i want to save a message to person’s file in the XX directory (with lots of abbreviated symlinks for frequent correspondents). the gmail “set folder” takes away the “+” option. but a workaround has been to insert “cd XX” at the start of .mailrc. that way i can just say ‘s person’. there are a couple of weird sideeffects but mostly it works well. other suggestions are welcome!

      1. @dave: Interesting. So the problem was the subdirectory? It sounds like `cd XX` solves the problem, so I’m not sure what more I could suggest. Perhaps using capital ‘C’ or capital ‘S’ so you don’t have to type the person’s name each time.

  18. @Eric Z. Ma: SECURITY ISSUE. I just realized that you told people to put their password in a plain text file, but left out that they should definitely NOT put their standard gmail password in. If you can, please edit the post so people know to generate an “App Password” specifically for mailx so it can be easily revoked if it ever leaks out. It’s super easy, just go to this URL:

    https://myaccount.google.com/apppasswords

    Click on “Select App” → “Other”, type “mailx”, and hit “Generate”. Bingo, you’ve got a new password you can cut and paste into your .mailrc.

    (Note: It is, of course, still necessary to `chmod 600 ~/.mailrc`).

  19. Actually, I just realized that, despite the date at the top of the article saying it was posted one month ago, it was actually eight years! Perhaps it’s time for an updated version of this blog post. (And, since search engines rank this post highly, maybe put a big link at the top to the new revision).

    Some differences I notice off the top of my head:

    1. nss is no longer necessary to set, nor is ssl-verify. It “just works” under Debian 8.10 and Ubuntu 16.04.

    2. Password security:
    2a. Any password entered as an argument on the command line can be seen by any other user on the system. (`ps auxwwe`)
    Even, if you’re the only user on your machine, attackers can sometimes run commands with low-privileges, for example, using a php exploit.
    2b. Any file with a plain text password should not be world readable: `chmod 600 ~/.mailrc ~/.netrc`.
    2c. Generate a unique App Password, as I mentioned in the previous comment.

    3. You do not need to set smtp-use-starttls if you have specified smtps as the protocol:

    set smtp=”smtps://smtp.gmail.com”

    4. heirloom-mailx has been superseded by s-nail. I’ve had no compatibility problems, but they do plan on cleaning up the .mailrc syntax in v15. For example, specifying the SMTP host, the username and password will be one command instead of three:

    set smtp=”smtps://USER:PASS@smtp.gmail.com”

    1. Thanks for the suggestions. For the date shown, it is the last update date. The original posting date will be shown if you hover the cursor on top of the date link.

      For the concrete comments:

      1. nss-config-dir is optional now as most Linux system’s default nssdb should be already updated. Using firefox’s dir should be needed only if the system’s one is too old. For the ssl-verify, for some commonly available systems, such as CentOS 7, it is still needed. Keeping it there should not be hurt although some newer systems already don’t require so. (Just a though: making ssl-verify to be ignore by default sounds some trade offs between security and assisting batching usage of the mailx).

      2. Good points.

      3. Unfortunately, similar to 1, smtps is not widely available yet.

      4. s-nail seems receive quite some new updates. Good to know mailx is back to be actively developed. heirloom-mailx development seems have been quiet for quite some years.

      BTW: we welcome contributes https://www.systutorials.com/contribute/ . If you would like to write one posts about your experiences on mailx and s-nail, please feel free to submit posts. Cheers!

  20. In Ubuntu 18.04, the package should be `s-nail` and the `mailx` command should be replaced with `s-nail`.

  21. Hello Eric,
    Just wanted to check whether can we use USERID and password of SMTP server’s authentication in mailx command as any of parameter? Does it requires newer version of Linux operating system or it supports on older version too?
    If it supports, what would be the syntax for that ? Thanks!!!

Leave a Reply

Your email address will not be published. Required fields are marked *