Guide

How to Send GPG Encrypted Email from the Command Line

Traditionally, sending GPG-encrypted email from the terminal means piping gpg output into mail, manually managing keys, and hoping the MIME structure is correct. The Nylas CLI wraps all of this into a single --encrypt flag with automatic key discovery.

The old way vs the new way

The traditional approach to GPG email from the terminal looks like this:

# Old way: pipe GPG into mail (fragile, no PGP/MIME)
gpg -ea -r "recipient@example.com" -o - message.txt | mail -s "Secret" recipient@example.com

This produces ASCII-armored inline PGP, not proper PGP/MIME. Many email clients struggle to verify or decrypt inline PGP. It also requires that the recipient's public key is already in your keyring -- you need to manually import it first.

The Nylas CLI handles all of this:

# New way: single command, proper PGP/MIME, auto key-fetch
nylas email send --to recipient@example.com --subject "Secret" --body "..." --sign --encrypt

Prerequisites

  1. GPG installed
    # macOS
    brew install gnupg
    
    # Debian/Ubuntu
    sudo apt install gnupg
    
    # Verify
    gpg --version
  2. A GPG key pair for your email address
    # Generate if you don't have one
    gpg --gen-key
    # Use the same email address as your Nylas account
  3. Nylas CLI installed and authenticated
    brew install nylas-cli/tap/nylas
    nylas auth login

Signing: prove the email is from you

Signing attaches a cryptographic signature to your email. Anyone with your public key can verify it came from you and was not tampered with. The content is still readable -- signing does not encrypt.

# Sign with your default key
nylas email send \
  --to colleague@company.com \
  --subject "Q4 Report" \
  --body "Please review the attached Q4 numbers." \
  --sign

# Sign with a specific key
nylas email send \
  --to colleague@company.com \
  --subject "Q4 Report" \
  --body "..." \
  --sign \
  --gpg-key 601FEE9B1D60185F

# List available signing keys
nylas email send --list-gpg-keys

Key selection priority

  1. --gpg-key flag (explicit override)
  2. gpg.default_key from Nylas config
  3. Auto-detected from your email address
  4. user.signingkey from git config

Auto-sign all outgoing email

# Enable auto-sign (no --sign flag needed on every send)
nylas config set gpg.auto_sign true

# All future emails are signed automatically
nylas email send --to team@co.com --subject "Update" --body "..."

# Disable when needed
nylas config set gpg.auto_sign false

Encrypting: hide the content

Encryption ensures only the intended recipient can read the message. The CLI uses the recipient's public key to encrypt. If the key is not in your local keyring, it automatically searches keyservers:

  • keys.openpgp.org (primary)
  • keyserver.ubuntu.com
  • pgp.mit.edu
  • keys.gnupg.net
# Encrypt to a recipient (key auto-fetched)
nylas email send \
  --to legal@partner.com \
  --subject "Contract draft v3" \
  --body "Attached are the revised terms." \
  --encrypt

# Encrypt with a specific recipient key
nylas email send \
  --to legal@partner.com \
  --subject "Contract" \
  --body "..." \
  --encrypt \
  --recipient-key ABCD1234EFGH5678

Sign + encrypt (recommended)

For maximum security, always use both. The CLI signs first (with your private key), then encrypts the signed content (with the recipient's public key):

nylas email send \
  --to legal@partner.com \
  --subject "Confidential: Board minutes" \
  --body "Minutes from today's board meeting." \
  --sign \
  --encrypt

This gives you:

  • Confidentiality -- only the recipient can decrypt
  • Authentication -- the recipient can verify it came from you
  • Integrity -- any tampering invalidates the signature

Reading encrypted email

# Decrypt an encrypted email you received
nylas email read msg_xyz789 --decrypt

# Decrypt AND verify the signature
nylas email read msg_xyz789 --decrypt --verify

# Verify a signed (but not encrypted) email
nylas email read msg_abc123 --verify

Example output

$ nylas email read msg_xyz789 --decrypt --verify

From: sender@example.com
To: you@example.com
Subject: Confidential Information

---
Message decrypted successfully
  Decrypted with: B6F0A2849DC14AA2

  Signature verified
  Signer: Alice <alice@example.com>
  Key ID: FF8780A3D2CDCCF4A5B38D3055023BA972AB76E8
---

This is the signed and encrypted message content.

Multi-recipient encryption

nylas email send \
  --to alice@team.com \
  --cc bob@team.com \
  --bcc charlie@team.com \
  --subject "Board meeting notes" \
  --body "Confidential notes from today." \
  --sign --encrypt

Each recipient can decrypt independently with their own private key. To/CC recipients are visible to all; BCC recipients are hidden but can still decrypt.

Key management

# List all public keys in your keyring
gpg --list-keys

# Import a key from a file
gpg --import colleague-key.asc

# Export your public key for sharing
gpg --armor --export you@company.com > my-key.asc

# Upload your key to a keyserver
gpg --keyserver keys.openpgp.org --send-keys YOUR_KEY_ID

# Verify a key fingerprint (do this over a secure channel)
gpg --fingerprint recipient@example.com

Troubleshooting

No public key found for recipient

The recipient has not published their key to any keyserver. Ask them to either share their public key file or upload it:

# They run:
gpg --keyserver keys.openpgp.org --send-keys THEIR_KEY_ID

# You import from file:
gpg --import their-key.asc

GPG passphrase prompt times out

# Start gpg-agent
gpg-agent --daemon

# Or configure pinentry for terminal
echo "pinentry-program /usr/bin/pinentry-tty" >> ~/.gnupg/gpg-agent.conf
gpgconf --kill gpg-agent

Recipient's key is expired

# Check expiration
gpg --list-keys recipient@example.com

# Ask them to extend or regenerate, then re-fetch
gpg --keyserver keys.openpgp.org --recv-keys THEIR_KEY_ID

Signing vs encrypting vs both

PropertySign onlyEncrypt onlySign + Encrypt
Content readable by anyoneYesNoNo
Verifies sender identityYesNoYes
Detects tamperingYesNoYes
Key used for sendYour private keyRecipient public keyBoth
Key used for readYour public keyRecipient private keyBoth

Next steps