Guide
Send GPG Encrypted Email from CLI
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 all major email providers.
Written by Aaron de Mello Senior Engineering Manager
Reviewed by Caleb Geene
Why is GPG email hard without a CLI?
Sending GPG-encrypted email from the terminal traditionally requires chaining multiple commands, manually importing recipient keys, and producing inline PGP that many email clients cannot parse. RFC 3156, published in August 2001, defines PGP/MIME as the correct format for encrypted email, yet most CLI tools still produce inline PGP instead.
The fragility of inline PGP is well-documented. Apple Mail, the Gmail web client, and Outlook on the web all fail to verify or decrypt inline PGP messages. The traditional approach pipes gpg output into mail, which produces ASCII-armored text rather than proper MIME parts:
# Old way: pipe GPG into mail (fragile, no PGP/MIME)
gpg -ea -r "recipient@example.com" -o - message.txt | mail -s "Secret" recipient@example.comThis produces ASCII-armored inline PGP, not proper PGP/MIME. It also requires the recipient's public key to already exist in your local keyring -- you need to run gpg --recv-keys or gpg --import manually before every new recipient. The keys.openpgp.org keyserver hosts over 1 million verified keys, and Nylas CLI auto-fetches recipient keys from it during encryption. One command replaces the entire pipe chain:
# New way: single command, proper PGP/MIME, auto key-fetch
nylas email send --to recipient@example.com --subject "Secret" --body "..." --sign --encryptPrerequisites
GPG email requires three components: the GnuPG encryption toolkit, a GPG key pair tied to your email address, and the Nylas CLI authenticated against your mail provider. GnuPG 2.2 or later is recommended -- earlier versions lack support for Ed25519 keys, which are now the default curve for new GPG keys since GnuPG 2.3.0 (released April 2021).
- GnuPG installed. GnuPG is available through system package managers on macOS and Linux. The
gpg --versioncommand confirms the installed version number and supported algorithms:# macOS brew install gnupg # Debian/Ubuntu sudo apt install gnupg # Verify gpg --version - A GPG key pair for your email address. The key pair consists of a private key (used for signing and decryption) and a public key (shared with recipients). The email address on the key must match the address on your Nylas account for signing to work:
# Generate if you don't have one gpg --gen-key # Use the same email address as your Nylas account - Nylas CLI installed and authenticated. Install via Homebrew, then authenticate with your mail provider through the browser-based OAuth flow. Authentication takes under 30 seconds:
brew install nylas/nylas-cli/nylas nylas auth login
How do I sign an email with GPG?
GPG signing attaches a cryptographic signature to an email so any recipient with your public key can verify that the message came from you and was not modified in transit. Signing does not encrypt -- the message body remains readable by anyone. According to the RFC 3156 Section 5 specification, a PGP/MIME signed message uses a multipart/signed content type with exactly 2 MIME parts.
The --sign flag produces a PGP/MIME signature. If you have multiple GPG keys, the --gpg-key flag lets you select a specific key by its 16-character hex ID. The --list-gpg-keys flag shows all keys available in your keyring:
# 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:00Key selection priority
--gpg-keyflag (explicit override)gpg.default_keyfrom Nylas config- Auto-detected from your email address
user.signingkeyfrom 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 falseHow do I encrypt an email?
GPG encryption transforms an email into ciphertext that only the intended recipient can decrypt using their private key. The Nylas CLI produces RFC 3156 PGP/MIME encrypted messages, which use a multipart/encrypted content type with AES-256 as the default symmetric cipher. If the recipient's public key is not already in your local keyring, the CLI automatically searches 4 keyservers in order:
- keys.openpgp.org (primary, over 1 million verified keys)
- keyserver.ubuntu.com
- pgp.mit.edu
- keys.gnupg.net
The --encrypt flag handles key discovery, download, and MIME formatting in a single step. Use --recipient-key to override auto-fetch and specify a key ID directly when you already have the recipient's fingerprint:
# 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 ABCD1234EFGH5678How do I sign and encrypt together?
Combining signing and encryption provides confidentiality, authentication, and integrity in a single message. The Nylas CLI follows the sign-then-encrypt order defined in RFC 3156: it first signs the plaintext with your private key, then encrypts the signed content with the recipient's public key. This order prevents an attacker from stripping the signature without also breaking the encryption.
Pass both --sign and --encrypt together. The CLI resolves the signing key from your keyring and the encryption key from keyservers (if not already cached locally), then wraps the result in a single PGP/MIME message:
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:00This gives you:
- Confidentiality -- only the recipient can decrypt
- Authentication -- the recipient can verify it came from you
- Integrity -- any tampering invalidates the signature
How do I read encrypted email?
Reading GPG-encrypted email requires the private key that matches the public key used during encryption. The Nylas CLI decrypts the PGP/MIME message locally using your GnuPG keyring -- no plaintext ever leaves your machine. The --verify flag additionally checks the sender's signature against their public key, confirming both authorship and message integrity.
GnuPG prompts for your key passphrase during decryption unless you have gpg-agent caching enabled (default cache timeout is 600 seconds). Use --decrypt alone or combine it with --verify to decrypt and check the signature in one step:
# 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 --verifyExample 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]How do I encrypt for multiple recipients?
PGP/MIME supports encrypting a single message for multiple recipients by creating a separate encrypted session key for each recipient's public key. The Nylas CLI auto-fetches keys for every address in --to, --cc, and --bcc fields. According to RFC 4880 Section 5.1, each recipient gets a Public-Key Encrypted Session Key packet, so the message body is encrypted only once while remaining decryptable by each individual recipient.
The CLI resolves public keys for all recipients before sending. If any recipient's key cannot be found on the 4 configured keyservers, the send fails with an error rather than sending an unencrypted message:
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 --encryptEach recipient decrypts independently with their own private key. To and CC recipients are visible to all parties. BCC recipients are hidden from other recipients but can still decrypt the message.
How do I manage GPG keys?
GPG keys have a finite lifespan -- the default expiration when generating a new key is 2 years, though many organizations set 1-year expirations for compliance. Managing keys means importing recipient keys, exporting your own for sharing, uploading to keyservers, and verifying fingerprints over a trusted channel. The GnuPG keyring stores all keys locally in ~/.gnupg/.
These are the standard GnuPG commands for key management. Always verify a recipient's full 40-character fingerprint over a secure channel (phone call, in-person, or signed message) before trusting their key for encryption:
# 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.compub 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
GPG email errors fall into three categories: missing keys, agent configuration issues, and expired keys. The fixes below cover the most common failures. According to the GnuPG FAQ, passphrase agent issues account for the majority of user-reported problems on macOS and Linux.
No public key found for recipient
This error means the recipient has not published their key to any of the 4 keyservers the CLI searches. The fix is to either have the recipient upload their key or import it manually from a file they share with you:
# They run:
gpg --keyserver keys.openpgp.org --send-keys THEIR_KEY_ID
# You import from file:
gpg --import their-key.ascGPG passphrase prompt times out
The gpg-agent daemon handles passphrase caching and prompts. If it is not running or is configured for a GUI pinentry on a headless system, the passphrase prompt times out after the default 150-second pinentry-timeout. Restart the agent or switch to a terminal-compatible pinentry program:
# 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-agentRecipient's key is expired
GnuPG refuses to encrypt to an expired key. The gpg --list-keys output shows [expired: YYYY-MM-DD] next to the key. Ask the recipient to extend their key's expiration date or generate a new key pair, then re-fetch the updated key from the keyserver:
# 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_IDpub 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]When should I sign vs encrypt vs both?
Signing, encrypting, and sign+encrypt serve different security goals. Signing alone proves authorship without hiding content -- useful for open-source release announcements or internal memos where authenticity matters more than secrecy. Encrypting alone hides content but does not prove who sent it. Sign+encrypt provides all 3 properties (confidentiality, authentication, integrity) and is the recommended default for sensitive communication.
| Property | Sign only | Encrypt only | Sign + Encrypt |
|---|---|---|---|
| Content readable by anyone | Yes | No | No |
| Verifies sender identity | Yes | No | Yes |
| Detects tampering | Yes | No | Yes |
| Key used for send | Your private key | Recipient public key | Both |
| Key used for read | Your public key | Recipient private key | Both |
Next steps
- Full email guide -- sending, reading, searching, scheduling, and automation
- AI agent email access via MCP -- give Claude or Cursor access to your inbox
- Command reference -- every flag documented
- GnuPG documentation -- deep dive into GPG itself