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. GPG encryption works across Gmail, Outlook, Exchange, Yahoo, iCloud, and IMAP.

By Aaron de Mello

The old way vs the new way

RFC 3156, published in August 2001, defines PGP/MIME as the standard for encrypted email — yet most CLI tools still produce inline PGP, which many modern email clients (including Apple Mail and the Gmail web client) cannot verify or decrypt.

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 keys.openpgp.org keyserver hosts over 1 million verified keys, and Nylas CLI auto-fetches recipient keys from it during encryption. It 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. GnuPG 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/nylas-cli/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
✓ Email sent (signed)

  Message ID: msg_4u3t2s1r0q9p
  To: team@example.com
  Subject: Release notes v2.4.0
  Signature: 0x1234ABCD5678EF90
  Format: PGP/MIME (RFC 3156)
  Sent at: 2026-03-25T16:50:00-04:00

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:

# 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
✓ Email sent (signed + encrypted)

  Message ID: msg_9x8y7z6w5v4u
  To: recipient@example.com
  Subject: Confidential: Q2 financials
  GPG Key: 0xAB12CD34EF567890 (auto-fetched from keys.openpgp.org)
  Signature: 0x1234ABCD5678EF90 (your default key)
  Format: PGP/MIME (RFC 3156)
  Sent at: 2026-03-25T16:45:00-04:00

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.
gpg: Signature made Tue Mar 25 16:45:00 2026 EDT
gpg:                using EDDSA key AB12CD34EF567890AB12CD34EF567890AB12CD34
gpg: Good signature from "Sarah Chen <sarah@example.com>" [full]

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
pub   ed25519 2024-01-15 [SC] [expires: 2027-01-14]
      AB12CD34EF567890AB12CD34EF567890AB12CD34
uid           [ultimate] Alex Rivera <alex@example.com>
sub   cv25519 2024-01-15 [E] [expires: 2027-01-14]

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
pub   ed25519 2024-01-15 [SC] [expired: 2025-01-14]
      CD56EF78AB901234CD56EF78AB901234CD56EF78
uid           [ expired] Jordan Lee <jordan@example.com>
sub   cv25519 2024-01-15 [E] [expired: 2025-01-14]

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