Category Archives: Email

Sending mail on the Linux command line (Ubuntu 18.04)

How to send end-to-end encrypted emails on the Linux command line.

If you want to add attachments, use mutt or mail from GNU Mailutils as the mail client. The following examples use mailx and ssmtp.

Unencrypted mail

Install package "bsd-mailx":

$ sudo apt-get install bsd-mailx

Edit /etc/mail.rc and add the following lines:

set smtp=smtp://
alias root

Run mailx:

$ mailx root
Subject: test 
This is a test. 


  • Mail gets sent to (see mail.rc).
  • Mail server is (see mail.rc).
  • Email message body is terminated by a single "." as the last line.

Encrypted mail (Inline PGP)

Make sure you can send unencrypted mail (s. "Unencrypted mail" above).

Check that you have GnuPG version 2 installed, and If you haven't done so before, create private and public GnuPG key.

$ gpg --version
gpg (GnuPG) 2.2.4
libgcrypt 1.8.1
$ gpg --gen-key

Import public PGP key from recipient.

$ gpg --import

First sign message (clearsign - ascii signature will be appended to text), then encrypt message, then mail message.

$ echo "Hello Alice, if you can read this your PGP mail client is working." | \
    gpg --clearsign | \
    gpg -a -r --encrypt | \
    mailx -s "PGP encrypted mail test"


  • First sign the message. "gpg --clearsign" uses the default private key to sign message. Check with "gpg -K". Otherwise use option "--default-key" to choose a specific private key.
  • Then encrypt the message. Check with "gpg -k" that recipient is properly added to your GPG keyring.
  • Finally send mail message. Email body is simply the signed and encrypted message text in ASCII format.
  • Email subject will not be encrypted.

Encrypted mail (S/MIME)

Make sure you can send unencrypted mail (s. "Unencrypted mail" above).

You need your own public certificate / private key pair, and the public certificate from the recipient (all in PEM format).

You can get a S/MIME email certificate for free from COMODO. Or you run your own certificate authority. Either way, both your own certificate and your own key need to be in a single file in PEM format (in the following example it is called "bob.pem").


The public certificate of the recipient must be in PEM format too (in the following example it is called "alice.pem"). You can extract it from an email signature if the recipient already sent you a signed email.


Install the package "ssmtp".

$ sudo apt-get install ssmtp

Again (as in the above example for PGP encrypted mail), all commands for signing, encrypting and sending the message can be chained together to a single command line.

$ echo "Hello Alice, if you can read this your S/MIME mail client is working." | \
    openssl smime -sign -signer bob.pem -text | \
    openssl smime -encrypt -from -to -subject "S/MIME encrypted mail test" -aes-256-cbc alice.pem | \
    ssmtp -t


  • Email body is simply the signed and encrypted message text in ASCII format. OpenSSL adds all required headers to it (sender, recipient, subject).
  • If you are using a S/MIME certificate from a public CA (like COMODO) to sign your message, it is easier for the recipient to validate your signature, compared to PGP encrypted emails.
  • You still need the public certificate of the recipient, and make somehow sure that it is authentic.
  • Again, the email subject will not be encrypted.

Pinentry not working over SSH with x11forwarding (Thunderbird with Enigmail)

If you use Enigmail in Thunderbird over a SSH connection, sometimes you cannot input the passphrase for your private GPG key. pinentry-qt / pinentry-gnome3 / pinentry-gtk2 are not showing any dialog boxes.

Here is a workaround: You can cache the passphrase with gpg-agent, even if Thunderbird is already running. Enigmail will then use the cached passphrase from gpg-agent, because it runs gpg2 commands in a subshell in order to encrypt or sign messages.

Connect to the server using x11forwarding:

$ ssh -Y server

Note your DISPLAY environment variable:

$ echo $DISPLAY

Unset / delete the DISPLAY environment variable:


Export GPG_TTY environment variable for gpg:

export GPG_TTY=$(tty)

Make sure that gpg-agent is running:

$ ps aux | grep gpg-agent
user 2058 0.0 0.0 168068 2228 ? Ss Nov10 0:07 gpg-agent --homedir /home/user/.gnupg --use-standard-socket --daemon

Insert the passphrase for your GPG key in gpg-agent by signing a dummy message. Make sure that you enter your passphrase in the pinentry tui not the gpg command prompt.

$ echo test | gpg2 --use-agent -s

The passphrase you are about to enter should be cached by gpg-agent. The cache lifetime is controlled by settings in ~/.gnupg/gpg-agent.conf . Now set the DISPLAY environment variable again to run Thunderbird. Use the value from previous command.

export DISPLAY=localhost:10.0

Start Thunderbird. You should now be able to sign and encrypt email messages with Enigmail without having to enter your gpg passphrase again because it is already cached by gpg-agent.

thunderbird &