[PATCH] list-unsubscribe command
I've patched mutt to fit my needs.
Feel free to what you want with it :)
--------------------------------------------------------------
Aim
If you are subscribed to a lot of mailing-list, you must want
sometimes to unsubscribe some of them. This feature is here to
help you in this job. Just press 'X' when browsing a mailing
list in mutt.
--------------------------------------------------------------
Feature
provide a new command named 'list-unsubscribe', which is mapped
on the 'X' keystroke.
When lauching this command, mutt will read the header
'List-Unsubscribe' in the selected mail and prepare a new
mail with :
- to: <email-list-unsubscribe>
- subject: unsubscribe
- body : empty
Where <email-list-unsubscribe> is the mail found in the header.
--------------------------------------------------------------
patch : see the file attached
--
---------------------------------------------------------------------
* Alexis Sukrieh <sukria@xxxxxxxxxx>
* http://www.sukria.net
---------------------------------------------------------------------
"All mail clients suck. Mutt just sucks less." - http://www.mutt.org
Index: VERSION
===================================================================
RCS file: /home/roessler/cvs/mutt/VERSION,v
retrieving revision 3.8
diff -u -b -B -r3.8 VERSION
--- VERSION 1 Feb 2004 18:26:11 -0000 3.8
+++ VERSION 26 Apr 2004 18:25:51 -0000
@@ -1 +1 @@
-1.5.6
+1.5.7
Index: curs_main.c
===================================================================
RCS file: /home/roessler/cvs/mutt/curs_main.c,v
retrieving revision 3.17
diff -u -b -B -r3.17 curs_main.c
--- curs_main.c 12 Apr 2004 20:33:33 -0000 3.17
+++ curs_main.c 26 Apr 2004 18:25:53 -0000
@@ -1836,6 +1836,16 @@
menu->redraw = REDRAW_FULL;
break;
+ case OP_LIST_UNSUBSCRIBE:
+
+ CHECK_ATTACH;
+ CHECK_MSGCOUNT;
+ CHECK_VISIBLE;
+ ci_send_message (SENDREPLY|SENDLISTUNSUBSCRIBE, NULL, NULL, Context,
tag ? NULL : CURHDR);
+ menu->redraw = REDRAW_FULL;
+ break;
+
+
case OP_LIST_REPLY:
CHECK_ATTACH;
@@ -1876,9 +1886,7 @@
break;
CHECK_MSGCOUNT;
CHECK_VISIBLE;
- if (tag || !(CURHDR->security & PGP_TRADITIONAL_CHECKED))
mutt_check_traditional_pgp (tag ? NULL : CURHDR, &menu->redraw);
-
if (menu->menu == MENU_PAGER)
{
op = OP_DISPLAY_MESSAGE;
Index: pager.c
===================================================================
RCS file: /home/roessler/cvs/mutt/pager.c,v
retrieving revision 3.14
diff -u -b -B -r3.14 pager.c
--- pager.c 12 Apr 2004 20:33:33 -0000 3.14
+++ pager.c 26 Apr 2004 18:25:54 -0000
@@ -2174,17 +2174,6 @@
redraw = REDRAW_FULL;
break;
- case OP_CHECK_TRADITIONAL:
- CHECK_MODE (IsHeader (extra));
- if (!(WithCrypto & APPLICATION_PGP))
- break;
- if (!(extra->hdr->security & PGP_TRADITIONAL_CHECKED))
- {
- ch = -1;
- rc = OP_CHECK_TRADITIONAL;
- }
- break;
-
case OP_CREATE_ALIAS:
CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra));
if (IsMsgAttach (extra))
@@ -2383,7 +2372,7 @@
case OP_MAIL:
CHECK_MODE(IsHeader (extra) && !IsAttach (extra));
CHECK_ATTACH;
- ci_send_message (0, NULL, NULL, extra->ctx, extra->hdr);
+ ci_send_message (0, NULL, NULL, NULL, NULL);
redraw = REDRAW_FULL;
break;
@@ -2425,6 +2414,18 @@
extra->idxlen, extra->bdy,
SENDREPLY|SENDLISTREPLY);
else
ci_send_message (SENDREPLY | SENDLISTREPLY, NULL, NULL, extra->ctx,
extra->hdr);
+ redraw = REDRAW_FULL;
+ break;
+
+
+ case OP_LIST_UNSUBSCRIBE:
+ CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra));
+ CHECK_ATTACH;
+ if (IsMsgAttach (extra))
+ mutt_attach_reply (extra->fp, extra->hdr, extra->idx,
+ extra->idxlen, extra->bdy,
SENDREPLY|SENDLISTREPLY);
+ else
+ ci_send_message (SENDREPLY | SENDLISTUNSUBSCRIBE, NULL, NULL,
extra->ctx, extra->hdr);
redraw = REDRAW_FULL;
break;
Index: parse.c
===================================================================
RCS file: /home/roessler/cvs/mutt/parse.c,v
retrieving revision 3.10
diff -u -b -B -r3.10 parse.c
--- parse.c 19 Sep 2003 13:03:26 -0000 3.10
+++ parse.c 26 Apr 2004 18:25:56 -0000
@@ -916,6 +917,35 @@
return (r);
}
+/* extract the first substring that looks like a unsubscribe mailbox */
+static char *extract_unsubscribe_addr (const char *s)
+{
+ int part = 0;
+ char *email = safe_malloc(STRING);
+ char *last;
+
+ /* if the mailto link is devided in two parts : mailto:emailaddr?options
+ * just take the first one */
+ if ( (strchr (s, '?')) != NULL)
+ s = strtok (s, "?");
+
+ /* now split on the ':' char in order to take the email addr after "mailto:
" */
+ while ((s = strtok (s, ":")) != NULL)
+ {
+ if (++part > 1) {
+ if ((last = strchr (s, '>')) != NULL)
+ *last = '\0';
+ sprintf (email, "%s", s); /* __SPRINTF_CHECKED__ */
+ return email;
+ }
+ s = NULL;
+ }
+
+ return email;
+}
+
+
+
void mutt_parse_mime_message (CONTEXT *ctx, HEADER *cur)
{
MESSAGE *msg;
@@ -946,6 +976,7 @@
if (lastp)
last = *lastp;
+
switch (ascii_tolower (line[0]))
{
case 'a':
@@ -961,6 +992,7 @@
}
break;
+
case 'b':
if (ascii_strcasecmp (line+1, "cc") == 0)
{
@@ -1064,6 +1096,13 @@
matched = 1;
}
+ else if (ascii_strcasecmp (line, "List-Unsubscribe") == 0)
+ {
+ char *buf;
+ buf = extract_unsubscribe_addr (p);
+ e->list_unsubscribe = rfc822_parse_adrlist (e->list_unsubscribe, buf);
+ matched = 1;
+ }
break;
case 'm':
@@ -1333,6 +1373,7 @@
rfc2047_decode_adrlist (e->cc);
rfc2047_decode_adrlist (e->reply_to);
rfc2047_decode_adrlist (e->mail_followup_to);
+ rfc2047_decode_adrlist (e->list_unsubscribe);
rfc2047_decode_adrlist (e->return_path);
rfc2047_decode_adrlist (e->sender);
Index: recvattach.c
===================================================================
RCS file: /home/roessler/cvs/mutt/recvattach.c,v
retrieving revision 3.13
diff -u -b -B -r3.13 recvattach.c
--- recvattach.c 12 Apr 2004 20:33:33 -0000 3.13
+++ recvattach.c 26 Apr 2004 18:25:56 -0000
@@ -816,7 +816,7 @@
break;
/* functions which are passed through from the pager */
case OP_CHECK_TRADITIONAL:
- if (!(WithCrypto & APPLICATION_PGP) || (hdr && hdr->security &
PGP_TRADITIONAL_CHECKED))
+ if (!(WithCrypto & APPLICATION_PGP))
{
op = OP_NULL;
break;
@@ -1159,6 +1159,11 @@
menu->redraw = REDRAW_FULL;
break;
+ case OP_LIST_UNSUBSCRIBE:
+
+ menu->redraw = REDRAW_FULL;
+
+ break;
case OP_EDIT_TYPE:
mutt_edit_content_type (hdr, idx[menu->current]->content, fp);
mutt_update_attach_index (cur, &idx, &idxlen, &idxmax, menu);
Index: send.c
===================================================================
RCS file: /home/roessler/cvs/mutt/send.c,v
retrieving revision 3.30
diff -u -b -B -r3.30 send.c
--- send.c 12 Apr 2004 21:19:27 -0000 3.30
+++ send.c 26 Apr 2004 18:25:58 -0000
@@ -436,6 +436,13 @@
{
char prompt[STRING];
+ /* If this is a list-unsubscribe command, the To: is the mail addr found in
+ * the header called "List-Unsubscribe"*/
+ if (flags & SENDLISTUNSUBSCRIBE) {
+ rfc822_append (to, env->list_unsubscribe);
+ return 0;
+ }
+
if (flags && env->mail_followup_to && hmfupto == M_YES)
{
rfc822_append (to, env->mail_followup_to);
@@ -448,6 +455,7 @@
if (flags & SENDLISTREPLY)
return 0;
+
if (!option(OPTREPLYSELF) && mutt_addr_is_user (env->from))
{
/* mail is from the user, assume replying to recipients */
@@ -512,7 +520,7 @@
ADDRESS *tmp;
int hmfupto = -1;
- if ((flags & (SENDLISTREPLY|SENDGROUPREPLY)) && in->mail_followup_to)
+ if ((flags & (SENDLISTUNSUBSCRIBE | SENDLISTREPLY | SENDGROUPREPLY)) &&
in->mail_followup_to)
{
snprintf (prompt, sizeof (prompt), _("Follow-up to %s%s?"),
in->mail_followup_to->mailbox,
@@ -522,6 +530,26 @@
return -1;
}
+
+ if ((flags & SENDLISTUNSUBSCRIBE) && in->list_unsubscribe)
+ {
+ /* snprintf (prompt, sizeof (prompt), _("Unsubscribe address : %s ?"),
+ in->list_unsubscribe->mailbox);
+
+ if ((hmfupto = query_quadoption (OPT_MFUPTO, prompt)) == -1)
+ return -1;
+ */
+
+ out->to = NULL;
+ rfc822_append (&out->to, in->list_unsubscribe);
+ return 0;
+ }
+
+ else if (flags & SENDLISTUNSUBSCRIBE) {
+ mutt_error _("Unable to find the List-Unsubscribe header.");
+ return -1;
+ }
+
if (flags & SENDLISTREPLY)
{
tmp = find_mailing_lists (in->to, in->cc);
@@ -702,13 +730,20 @@
else if (mutt_fetch_recips (env, curenv, flags) == -1)
return -1;
- if ((flags & SENDLISTREPLY) && !env->to)
+ if ((flags & (SENDLISTREPLY)) && !env->to)
{
- mutt_error _("No mailing lists found!");
+ mutt_error _("No mailing lists found");
return (-1);
}
+ /* FIXME : need to get the real subject token and put 'unsubscribe' byu
default */
+ if (flags & SENDLISTUNSUBSCRIBE) {
+ env->subject = safe_malloc (mutt_strlen ("unsubscribe") + 1);
+ sprintf (env->subject, "unsubscribe");
+ }
+ else {
mutt_make_misc_reply_headers (env, ctx, cur, curenv);
+ }
mutt_make_reference_headers (tag ? NULL : curenv, env, ctx);
}
else if (flags & SENDFORWARD)
@@ -728,7 +763,12 @@
HEADER *h;
BODY *tmp;
- if (flags & SENDREPLY)
+ if (flags & SENDLISTUNSUBSCRIBE) {
+ /* empty body for list-unsubscribe mails */
+ return (0);
+ }
+
+ else if (flags & SENDREPLY)
{
if ((i = query_quadoption (OPT_INCLUDE, _("Include message in reply?")))
== -1)
return (-1);
@@ -859,9 +899,7 @@
if (e->mail_followup_to && !mutt_is_list_recipient (0, e->to, e->cc))
{
- if (e->reply_to)
- from = rfc822_cpy_adr (e->reply_to);
- else if (e->from)
+ if (e->from)
from = rfc822_cpy_adr (e->from);
else
from = mutt_default_from ();
@@ -1157,6 +1195,7 @@
mutt_copy_stream (stdin, tempfp);
if (option (OPTHDRS))
{
+ if (! (flags & SENDLISTUNSUBSCRIBE))
process_user_recips (msg->env);
process_user_header (msg->env);
}
@@ -1168,8 +1207,9 @@
envelope_defaults (msg->env, ctx, cur, flags) == -1)
goto cleanup;
- if (option (OPTHDRS))
+ if (option (OPTHDRS)) {
process_user_recips (msg->env);
+ }
/* Expand aliases and remove duplicates/crossrefs */
mutt_fix_reply_recipients (msg->env);
@@ -1196,7 +1236,7 @@
if ((flags & SENDREPLY) && cur)
{
/* change setting based upon message we are replying to */
- mutt_message_hook (ctx, cur, M_REPLYHOOK);
+ mutt_message_hook (NULL, cur, M_REPLYHOOK);
/*
* set the replied flag for the message we are generating so that the
@@ -1256,13 +1296,6 @@
msg->security |= SIGN;
if (option (OPTCRYPTREPLYSIGNENCRYPTED) && cur && (cur->security &
ENCRYPT))
msg->security |= SIGN;
- if (WithCrypto & APPLICATION_PGP && (msg->security & (ENCRYPT | SIGN)))
- {
- if (option (OPTPGPAUTOINLINE))
- msg->security |= INLINE;
- if (option (OPTPGPREPLYINLINE) && cur && (cur->security & INLINE))
- msg->security |= INLINE;
- }
}
if (WithCrypto && msg->security)
@@ -1312,7 +1345,7 @@
&& !(flags & (SENDRESEND|SENDPOSTPONED)))
msg->env->from->personal = safe_strdup (Realname);
- if (!((WithCrypto & APPLICATION_PGP) && (flags & SENDKEY)))
+ if ((WithCrypto & APPLICATION_PGP) && !(flags & SENDKEY))
safe_fclose (&tempfp);
if (flags & SENDMAILX)
@@ -1501,7 +1534,7 @@
clear_content = msg->content;
if ((crypt_get_keys (msg, &pgpkeylist) == -1) ||
- mutt_protect (msg, pgpkeylist) == -1)
+ mutt_protect (msg, cur, pgpkeylist) == -1)
{
msg->content = mutt_remove_multipart (msg->content);
@@ -1581,7 +1614,7 @@
/* this means writing only the main part */
msg->content = clear_content->parts;
- if (mutt_protect (msg, pgpkeylist) == -1)
+ if (mutt_protect (msg, cur, pgpkeylist) == -1)
{
/* we can't do much about it at this point, so
* fallback to saving the whole thing to fcc
@@ -1684,6 +1717,10 @@
if (WithCrypto && free_clear_content)
mutt_free_body (&clear_content);
+ if (flags & SENDLISTUNSUBSCRIBE) {
+ msg->content = NULL;
+ }
+ else
if (flags & SENDREPLY)
{
if (cur && ctx)