<<< Date Index >>>     <<< Thread Index >>>

[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)