From: Kevin McCarthy Date: Fri, 19 Jul 2019 19:54:32 +0000 (-0700) Subject: Add autocrypt line to the compose menu X-Git-Tag: 2019-10-25~97^2~39 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7e6993900bd8514eeba604a49f01277f9add1479;p=neomutt Add autocrypt line to the compose menu Remove the hardcoded HDR_ATTACH offset calcuation, and add an explicit enum for the "-- Attachments" line to make loops and padding array sizes easier. Add security and recommendataion fields on the line. Add mutt_autocrypt_ui_recommendation, following the autocrypt spec guidelines. Co-authored-by: Richard Russon --- diff --git a/autocrypt/autocrypt.c b/autocrypt/autocrypt.c index feb204e8b..cf5d7c193 100644 --- a/autocrypt/autocrypt.c +++ b/autocrypt/autocrypt.c @@ -35,6 +35,7 @@ #include "curs_lib.h" #include "globals.h" #include "mutt_curses.h" +#include "ncrypt/ncrypt.h" #include "send.h" static int autocrypt_dir_init(int can_create) @@ -448,3 +449,76 @@ cleanup: return rv; } + +enum AutocryptRec mutt_autocrypt_ui_recommendation(struct Email *hdr) +{ + enum AutocryptRec rv = AUTOCRYPT_REC_OFF; + struct AutocryptAccount *account = NULL; + struct AutocryptPeer *peer = NULL; + struct Address *recip = NULL; + int all_encrypt = 1, has_discourage = 0; + + if (!C_Autocrypt || mutt_autocrypt_init(0) || !hdr) + return AUTOCRYPT_REC_OFF; + + struct Address *from = TAILQ_FIRST(&hdr->env->from); + if (!from || TAILQ_NEXT(from, entries)) + return AUTOCRYPT_REC_OFF; + + if (hdr->security & APPLICATION_SMIME) + return AUTOCRYPT_REC_OFF; + + if (mutt_autocrypt_db_account_get(from, &account) <= 0) + goto cleanup; + + struct AddressList recips = TAILQ_HEAD_INITIALIZER(recips); + + mutt_addrlist_copy(&recips, &hdr->env->to, false); + mutt_addrlist_copy(&recips, &hdr->env->cc, false); + mutt_addrlist_copy(&recips, &hdr->env->bcc, false); + + rv = AUTOCRYPT_REC_NO; + if (TAILQ_EMPTY(&recips)) + goto cleanup; + + TAILQ_FOREACH(recip, &recips, entries) + { + if (mutt_autocrypt_db_peer_get(recip, &peer) <= 0) + goto cleanup; + + if (mutt_autocrypt_gpgme_is_valid_key(peer->keyid)) + { + if (!(peer->last_seen && peer->autocrypt_timestamp) || + (peer->last_seen - peer->autocrypt_timestamp > 35 * 24 * 60 * 60)) + { + has_discourage = 1; + all_encrypt = 0; + } + + if (!account->prefer_encrypt || !peer->prefer_encrypt) + all_encrypt = 0; + } + else if (mutt_autocrypt_gpgme_is_valid_key(peer->gossip_keyid)) + { + has_discourage = 1; + all_encrypt = 0; + } + else + goto cleanup; + + mutt_autocrypt_db_peer_free(&peer); + } + + if (all_encrypt) + rv = AUTOCRYPT_REC_YES; + else if (has_discourage) + rv = AUTOCRYPT_REC_DISCOURAGE; + else + rv = AUTOCRYPT_REC_AVAILABLE; + +cleanup: + mutt_autocrypt_db_account_free(&account); + mutt_addrlist_clear(&recips); + mutt_autocrypt_db_peer_free(&peer); + return rv; +} diff --git a/autocrypt/autocrypt.h b/autocrypt/autocrypt.h index 82dc6a9b1..d3f10fa4f 100644 --- a/autocrypt/autocrypt.h +++ b/autocrypt/autocrypt.h @@ -67,9 +67,19 @@ struct AutocryptGossipHistory char *gossip_keydata; }; +enum AutocryptRec +{ + AUTOCRYPT_REC_OFF, + AUTOCRYPT_REC_NO, + AUTOCRYPT_REC_DISCOURAGE, + AUTOCRYPT_REC_AVAILABLE, + AUTOCRYPT_REC_YES +}; + int mutt_autocrypt_init (int); void mutt_autocrypt_cleanup (void); int mutt_autocrypt_process_autocrypt_header (struct Email *hdr, struct Envelope *env); int mutt_autocrypt_process_gossip_header (struct Email *hdr, struct Envelope *env); +enum AutocryptRec mutt_autocrypt_ui_recommendation (struct Email *hdr); #endif /* MUTT_AUTOCRYPT_AUTOCRYPT_H */ diff --git a/autocrypt/autocrypt_gpgme.c b/autocrypt/autocrypt_gpgme.c index a4259a8ca..f8c33be3a 100644 --- a/autocrypt/autocrypt_gpgme.c +++ b/autocrypt/autocrypt_gpgme.c @@ -205,3 +205,28 @@ cleanup: mutt_buffer_pool_release(&raw_keydata); return rv; } + +int mutt_autocrypt_gpgme_is_valid_key(const char *keyid) +{ + int rv = 0; + gpgme_ctx_t ctx = NULL; + gpgme_key_t key = NULL; + + if (!keyid) + return 0; + + if (create_gpgme_context(&ctx)) + goto cleanup; + + if (gpgme_get_key(ctx, keyid, &key, 0)) + goto cleanup; + + rv = 1; + if (key->revoked || key->expired || key->disabled || key->invalid || !key->can_encrypt) + rv = 0; + +cleanup: + gpgme_key_unref(key); + gpgme_release(ctx); + return rv; +} diff --git a/autocrypt/autocrypt_private.h b/autocrypt/autocrypt_private.h index 258e4d085..8481d4536 100644 --- a/autocrypt/autocrypt_private.h +++ b/autocrypt/autocrypt_private.h @@ -63,5 +63,6 @@ int mutt_autocrypt_schema_update (void); int mutt_autocrypt_gpgme_init (void); int mutt_autocrypt_gpgme_create_key (struct Address *addr, struct Buffer *keyid, struct Buffer *keydata); int mutt_autocrypt_gpgme_import_key (const char *keydata, struct Buffer *keyid); +int mutt_autocrypt_gpgme_is_valid_key (const char *keyid); #endif /* MUTT_AUTOCRYPT_AUTOCRYPT_PRIVATE_H */ diff --git a/compose.c b/compose.c index 32a28d588..fc4d5dc4d 100644 --- a/compose.c +++ b/compose.c @@ -85,6 +85,9 @@ #ifdef USE_IMAP #include "imap/imap.h" #endif +#ifdef USE_AUTOCRYPT +#include "autocrypt/autocrypt.h" +#endif /* These Config Variables are only used in compose.c */ char *C_ComposeFormat; ///< Config: printf-like format string for the Compose panel's status bar @@ -121,15 +124,19 @@ enum HeaderField #endif HDR_CRYPT, ///< "Security:" field (encryption/signing info) HDR_CRYPTINFO, ///< "Sign as:" field (encryption/signing info) +#ifdef USE_AUTOCRYPT + HDR_AUTOCRYPT, +#endif #ifdef USE_NNTP HDR_NEWSGROUPS, ///< "Newsgroups:" field HDR_FOLLOWUPTO, ///< "Followup-To:" field HDR_XCOMMENTTO, ///< "X-Comment-To:" field #endif - HDR_ATTACH = (HDR_FCC + 5), ///< Position to start printing the attachments + HDR_ATTACH_TITLE, /* the "-- Attachments" line */ + HDR_ATTACH /* where to start printing the attachments */ }; -int HeaderPadding[HDR_XCOMMENTTO + 1] = { 0 }; +int HeaderPadding[HDR_ATTACH_TITLE] = { 0 }; int MaxHeaderWidth = 0; #define HDR_XOFFSET MaxHeaderWidth @@ -164,6 +171,12 @@ static const char *const Prompts[] = { Since it shares the row with "Encrypt with:", it should not be longer than 15-20 character cells. */ N_("Sign as: "), +#ifdef USE_AUTOCRYPT + /* L10N: + The compose menu autocrypt line + */ + N_("Autocrypt: "), +#endif #ifdef USE_NNTP /* L10N: Compose menu field. May not want to translate. */ N_("Newsgroups: "), @@ -202,6 +215,41 @@ static struct Mapping ComposeNewsHelp[] = { }; #endif +#ifdef USE_AUTOCRYPT +static const char *AutocryptRecUiFlags[] = { + /* L10N: Autocrypt recommendation flag: off. + * This is displayed when Autocrypt is turned off. */ + N_("Off"), + /* L10N: Autocrypt recommendation flag: no. + * This is displayed when Autocrypt cannot encrypt to the recipients. */ + N_("No"), + /* L10N: Autocrypt recommendation flag: discouraged. + * This is displayed when Autocrypt believes encryption should not be used. + * This might occur if one of the recipient Autocrypt Keys has not been + * used recently, or if the only key available is a Gossip Header key. */ + N_("Discouraged"), + /* L10N: Autocrypt recommendation flag: available. + * This is displayed when Autocrypt believes encryption is possible, but + * leaves enabling it up to the sender. Probably because "prefer encrypt" + * is not set in both the sender and recipient keys. */ + N_("Available"), + /* L10N: Autocrypt recommendation flag: yes. + * This is displayed when Autocrypt would normally enable encryption + * automatically. */ + N_("Yes"), +}; +#endif + +struct ComposeRedrawData +{ + struct Email *email; + char *fcc; +#ifdef USE_AUTOCRYPT + enum AutocryptRec autocrypt_rec; + int autocrypt_rec_override; +#endif +}; + /** * calc_header_width_padding - Calculate the width needed for the compose labels * @param idx Store the result at this index of HeaderPadding @@ -235,15 +283,19 @@ static void init_header_padding(void) return; done = true; - for (int i = 0; i <= HDR_XCOMMENTTO; i++) + for (int i = 0; i < HDR_ATTACH_TITLE; i++) + { + if (i == HDR_CRYPTINFO) + continue; calc_header_width_padding(i, _(Prompts[i]), true); + } /* Don't include "Sign as: " in the MaxHeaderWidth calculation. It * doesn't show up by default, and so can make the indentation of * the other fields look funny. */ calc_header_width_padding(HDR_CRYPTINFO, _(Prompts[HDR_CRYPTINFO]), false); - for (int i = 0; i <= HDR_XCOMMENTTO; i++) + for (int i = 0; i < HDR_ATTACH_TITLE; i++) { HeaderPadding[i] += MaxHeaderWidth; if (HeaderPadding[i] < 0) @@ -263,12 +315,51 @@ static void snd_make_entry(char *buf, size_t buflen, struct Menu *menu, int line MUTT_FORMAT_STAT_FILE | MUTT_FORMAT_ARROWCURSOR); } +#ifdef USE_AUTOCRYPT +static void autocrypt_compose_menu(struct Email *e) +{ + /* L10N: + The compose menu autocrypt prompt. + (e)ncrypt enables encryption via autocrypt. + (c)lear sets cleartext. + (a)utomatic defers to the recommendation. + */ + const char *prompt = _("Autocrypt: (e)ncrypt, (c)lear, (a)utomatic? "); + + /* L10N: + The letter corresponding to the compose menu autocrypt prompt + (e)ncrypt, (c)lear, (a)utomatic + */ + const char *letters = "eca"; + + int choice = mutt_multi_choice(prompt, letters); + switch (choice) + { + case 1: + e->security |= (SEC_AUTOCRYPT | SEC_AUTOCRYPT_OVERRIDE); + e->security &= ~(SEC_ENCRYPT | SEC_SIGN | SEC_OPPENCRYPT); + break; + case 2: + e->security &= ~SEC_AUTOCRYPT; + e->security |= SEC_AUTOCRYPT_OVERRIDE; + break; + case 3: + e->security &= ~SEC_AUTOCRYPT_OVERRIDE; + if (C_CryptOpportunisticEncrypt) + e->security |= SEC_OPPENCRYPT; + break; + } +} +#endif + /** * redraw_crypt_lines - Update the encryption info in the compose window * @param e Email */ -static void redraw_crypt_lines(struct Email *e) +static void redraw_crypt_lines(struct ComposeRedrawData *rd) { + struct Email *e = rd->email; + SET_COLOR(MT_COLOR_COMPOSE_HEADER); mutt_window_mvprintw(MuttIndexWindow, HDR_CRYPT, 0, "%*s", HeaderPadding[HDR_CRYPT], _(Prompts[HDR_CRYPT])); @@ -349,6 +440,64 @@ static void redraw_crypt_lines(struct Email *e) NORMAL_COLOR; printw("%s", NONULL(C_SmimeEncryptWith)); } + +#ifdef USE_AUTOCRYPT + mutt_window_move(MuttIndexWindow, HDR_AUTOCRYPT, 0); + mutt_window_clrtoeol(MuttIndexWindow); + SET_COLOR(MT_COLOR_COMPOSE_HEADER); + printw("%*s", HeaderPadding[HDR_AUTOCRYPT], _(Prompts[HDR_AUTOCRYPT])); + NORMAL_COLOR; + if (C_Autocrypt && (e->security & SEC_AUTOCRYPT)) + { + SET_COLOR(MT_COLOR_COMPOSE_SECURITY_ENCRYPT); + addstr(_("Encrypt")); + } + else + { + SET_COLOR(MT_COLOR_COMPOSE_SECURITY_NONE); + addstr(_("Off")); + } + + SET_COLOR(MT_COLOR_COMPOSE_HEADER); + mutt_window_mvprintw(MuttIndexWindow, HDR_AUTOCRYPT, 40, "%s", _("Recommendation: ")); + NORMAL_COLOR; + printw("%s", _(AutocryptRecUiFlags[rd->autocrypt_rec])); +#endif +} + +static void update_crypt_info(struct ComposeRedrawData *rd) +{ + struct Email *e = rd->email; + + if (C_CryptOpportunisticEncrypt) + crypt_opportunistic_encrypt(e); + +#ifdef USE_AUTOCRYPT + rd->autocrypt_rec = mutt_autocrypt_ui_recommendation(e); + + /* Anything that enables SEC_ENCRYPT or SEC_SIGN, or turns on SMIME + * overrides autocrypt, be it oppenc or the user having turned on + * those flags manually. */ + if (e->security & (SEC_ENCRYPT | SEC_SIGN | APPLICATION_SMIME)) + e->security &= ~(SEC_AUTOCRYPT | SEC_AUTOCRYPT_OVERRIDE); + else + { + if (!(e->security & SEC_AUTOCRYPT_OVERRIDE)) + { + if (rd->autocrypt_rec == AUTOCRYPT_REC_YES) + e->security |= SEC_AUTOCRYPT; + else + e->security &= ~SEC_AUTOCRYPT; + } + } + /* TODO: + * - autocrypt menu for manually enabling/disabling (turns on override) + * - deal with pgp and smime menu and their effects on security->SEC_AUTOCRYPT + * when encryption or signing is enabled or if switch to smime mode + */ +#endif + + redraw_crypt_lines(rd); } #ifdef MIXMASTER @@ -454,8 +603,11 @@ static void draw_envelope_addr(int line, struct AddressList *al) * @param e Email * @param fcc Fcc field */ -static void draw_envelope(struct Email *e, char *fcc) +static void draw_envelope(struct ComposeRedrawData *rd) { + struct Email *e = rd->email; + char *fcc = rd->fcc; + draw_envelope_addr(HDR_FROM, &e->env->from); #ifdef USE_NNTP if (!OptNewsSend) @@ -498,14 +650,14 @@ static void draw_envelope(struct Email *e, char *fcc) mutt_paddstr(W, fcc); if (WithCrypto) - redraw_crypt_lines(e); + redraw_crypt_lines(rd); #ifdef MIXMASTER redraw_mix_line(&e->chain); #endif SET_COLOR(MT_COLOR_STATUS); - mutt_window_mvaddstr(MuttIndexWindow, HDR_ATTACH - 1, 0, _("-- Attachments")); + mutt_window_mvaddstr(MuttIndexWindow, HDR_ATTACH_TITLE, 0, _("-- Attachments")); mutt_window_clrtoeol(MuttIndexWindow); NORMAL_COLOR; @@ -662,15 +814,6 @@ static void update_idx(struct Menu *menu, struct AttachCtx *actx, struct AttachP menu->current = actx->vcount - 1; } -/** - * struct ComposeRedrawData - Keep track when the compose screen needs redrawing - */ -struct ComposeRedrawData -{ - struct Email *email; - char *fcc; -}; - static void compose_status_line(char *buf, size_t buflen, size_t col, int cols, struct Menu *menu, const char *p); @@ -688,7 +831,7 @@ static void compose_custom_redraw(struct Menu *menu) { menu_redraw_full(menu); - draw_envelope(rd->email, rd->fcc); + draw_envelope(rd); menu->offset = HDR_ATTACH; menu->pagelen = MuttIndexWindow->rows - HDR_ATTACH; } @@ -890,7 +1033,7 @@ int mutt_compose_menu(struct Email *e, char *fcc, size_t fcclen, struct Email *e int rc = -1; bool loop = true; bool fcc_set = false; /* has the user edited the Fcc: field ? */ - struct ComposeRedrawData rd; + struct ComposeRedrawData rd = { 0 }; #ifdef USE_NNTP bool news = OptNewsSend; /* is it a news article ? */ #endif @@ -918,6 +1061,8 @@ int mutt_compose_menu(struct Email *e, char *fcc, size_t fcclen, struct Email *e actx->email = e; mutt_update_compose_menu(actx, menu, true); + update_crypt_info(&rd); + while (loop) { #ifdef USE_NNTP @@ -928,6 +1073,7 @@ int mutt_compose_menu(struct Email *e, char *fcc, size_t fcclen, struct Email *e { case OP_COMPOSE_EDIT_FROM: edit_address_list(HDR_FROM, &e->env->from); + update_crypt_info(&rd); mutt_message_hook(NULL, e, MUTT_SEND2_HOOK); break; @@ -937,11 +1083,7 @@ int mutt_compose_menu(struct Email *e, char *fcc, size_t fcclen, struct Email *e break; #endif edit_address_list(HDR_TO, &e->env->to); - if (C_CryptOpportunisticEncrypt) - { - crypt_opportunistic_encrypt(e); - redraw_crypt_lines(e); - } + update_crypt_info(&rd); mutt_message_hook(NULL, e, MUTT_SEND2_HOOK); break; @@ -951,11 +1093,7 @@ int mutt_compose_menu(struct Email *e, char *fcc, size_t fcclen, struct Email *e break; #endif edit_address_list(HDR_BCC, &e->env->bcc); - if (C_CryptOpportunisticEncrypt) - { - crypt_opportunistic_encrypt(e); - redraw_crypt_lines(e); - } + update_crypt_info(&rd); mutt_message_hook(NULL, e, MUTT_SEND2_HOOK); break; @@ -965,11 +1103,7 @@ int mutt_compose_menu(struct Email *e, char *fcc, size_t fcclen, struct Email *e break; #endif edit_address_list(HDR_CC, &e->env->cc); - if (C_CryptOpportunisticEncrypt) - { - crypt_opportunistic_encrypt(e); - redraw_crypt_lines(e); - } + update_crypt_info(&rd); mutt_message_hook(NULL, e, MUTT_SEND2_HOOK); break; #ifdef USE_NNTP @@ -1087,8 +1221,7 @@ int mutt_compose_menu(struct Email *e, char *fcc, size_t fcclen, struct Email *e mutt_error(_("Bad IDN in '%s': '%s'"), tag, err); FREE(&err); } - if (C_CryptOpportunisticEncrypt) - crypt_opportunistic_encrypt(e); + update_crypt_info(&rd); } else { @@ -1953,11 +2086,10 @@ int mutt_compose_menu(struct Email *e, char *fcc, size_t fcclen, struct Email *e } e->security &= ~APPLICATION_SMIME; e->security |= APPLICATION_PGP; - crypt_opportunistic_encrypt(e); - redraw_crypt_lines(e); + update_crypt_info(&rd); } e->security = crypt_pgp_send_menu(e); - redraw_crypt_lines(e); + update_crypt_info(&rd); mutt_message_hook(NULL, e, MUTT_SEND2_HOOK); break; @@ -1987,11 +2119,10 @@ int mutt_compose_menu(struct Email *e, char *fcc, size_t fcclen, struct Email *e } e->security &= ~APPLICATION_PGP; e->security |= APPLICATION_SMIME; - crypt_opportunistic_encrypt(e); - redraw_crypt_lines(e); + update_crypt_info(&rd); } e->security = crypt_smime_send_menu(e); - redraw_crypt_lines(e); + update_crypt_info(&rd); mutt_message_hook(NULL, e, MUTT_SEND2_HOOK); break; @@ -2000,6 +2131,28 @@ int mutt_compose_menu(struct Email *e, char *fcc, size_t fcclen, struct Email *e mix_make_chain(&e->chain); mutt_message_hook(NULL, e, MUTT_SEND2_HOOK); break; +#endif +#ifdef USE_AUTOCRYPT + case OP_COMPOSE_AUTOCRYPT_MENU: + if ((WithCrypto & APPLICATION_SMIME) && (e->security & APPLICATION_SMIME)) + { + if (e->security & (SEC_ENCRYPT | SEC_SIGN)) + { + if (mutt_yesorno(_("S/MIME already selected. Clear & continue ? "), MUTT_YES) != MUTT_YES) + { + mutt_clear_error(); + break; + } + e->security &= ~(SEC_ENCRYPT | SEC_SIGN); + } + e->security &= ~APPLICATION_SMIME; + e->security |= APPLICATION_PGP; + update_crypt_info(&rd); + } + autocrypt_compose_menu(e); + update_crypt_info(&rd); + mutt_message_hook(NULL, e, MUTT_SEND2_HOOK); + break; #endif } } diff --git a/email/email.h b/email/email.h index 6a2db383c..49c51c0e5 100644 --- a/email/email.h +++ b/email/email.h @@ -38,7 +38,7 @@ struct Notify; */ struct Email { - SecurityFlags security; ///< bit 0-9: flags, bit 10,11: application, bit 12 traditional pgp + SecurityFlags security; ///< bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp ///< See: ncrypt/ncrypt.h pgplib.h, smime.h bool mime : 1; ///< Has a MIME-Version header? diff --git a/functions.h b/functions.h index bfb5b9c23..b889ebfc8 100644 --- a/functions.h +++ b/functions.h @@ -451,6 +451,9 @@ const struct Binding OpCompose[] = { /* map: compose */ { "attach-message", OP_COMPOSE_ATTACH_MESSAGE, "A" }, #ifdef USE_NNTP { "attach-news-message", OP_COMPOSE_ATTACH_NEWS_MESSAGE, NULL }, +#endif +#ifdef USE_AUTOCRYPT + { "autocrypt-menu", OP_COMPOSE_AUTOCRYPT_MENU, "o" }, #endif { "copy-file", OP_SAVE, "C" }, { "detach-file", OP_DELETE, "D" }, diff --git a/ncrypt/ncrypt.h b/ncrypt/ncrypt.h index 81f7d158e..a69e2ca6e 100644 --- a/ncrypt/ncrypt.h +++ b/ncrypt/ncrypt.h @@ -128,12 +128,14 @@ typedef uint16_t SecurityFlags; ///< Flags, e.g. #SEC_ENCRYPT #define SEC_KEYBLOCK (1 << 6) ///< Email has a key attached #define SEC_INLINE (1 << 7) ///< Email has an inline signature #define SEC_OPPENCRYPT (1 << 8) ///< Opportunistic encrypt mode -#define SEC_AUTOCRYPT (1 << 9) ///< TODO: should this include the SEC_ENCRYPT and SEC_SIGN flags -#define APPLICATION_PGP (1 << 10) ///< Use PGP to encrypt/sign -#define APPLICATION_SMIME (1 << 11) ///< Use SMIME to encrypt/sign -#define PGP_TRADITIONAL_CHECKED (1 << 12) ///< Email has a traditional (inline) signature +#define SEC_AUTOCRYPT (1 << 9) ///< Message will be, or was Autocrypt encrypt+signed +#define SEC_AUTOCRYPT_OVERRIDE (1 << 10) ///< Indicates manual set/unset of encryption -#define SEC_ALL_FLAGS ((1 << 13) - 1) +#define APPLICATION_PGP (1 << 11) ///< Use PGP to encrypt/sign +#define APPLICATION_SMIME (1 << 12) ///< Use SMIME to encrypt/sign +#define PGP_TRADITIONAL_CHECKED (1 << 13) ///< Email has a traditional (inline) signature + +#define SEC_ALL_FLAGS ((1 << 14) - 1) #define PGP_ENCRYPT (APPLICATION_PGP | SEC_ENCRYPT) #define PGP_SIGN (APPLICATION_PGP | SEC_SIGN) diff --git a/opcodes.h b/opcodes.h index 6e7bd22ae..d9bab1d88 100644 --- a/opcodes.h +++ b/opcodes.h @@ -44,6 +44,7 @@ _fmt(OP_CHECK_STATS, N_("calculate message statistics for all mailboxes")) \ _fmt(OP_COMPOSE_ATTACH_FILE, N_("attach files to this message")) \ _fmt(OP_COMPOSE_ATTACH_MESSAGE, N_("attach messages to this message")) \ + _fmt(OP_COMPOSE_AUTOCRYPT_MENU, N_("show autocrypt compose menu options")) \ _fmt(OP_COMPOSE_ATTACH_NEWS_MESSAGE, N_("attach news articles to this message")) \ _fmt(OP_COMPOSE_EDIT_BCC, N_("edit the BCC list")) \ _fmt(OP_COMPOSE_EDIT_CC, N_("edit the CC list")) \