Voila, j'y suis, avant que ce patch soi soumis aux "gurus" de mutt-dev,
je propose aux personnes intéressées d'y jeter un oeil :)

-----------------------------------------------------------------------
Ce qui m'a amené à plonger dans le code source de mutt est le fait que je suis inscrit 
à de nombreuses listes de diffusion et que j'aime m'inscrire ici et me désinscrire là 
assez fréquemment. En fait je m'inscrit souvent pour voir si le contenu de la liste 
m'intéresse réellement et si son trafic n'est pas trop important.

Du coup j'avais vraiment envie que mutt puisse me proposer simplement un mail type de 
désinscription pour une liste donnée.

J'ai remarqué que dans la plupart des mails envoyés par les listes de diffusion, un 
en-tête est renseigné : "List-Unsubscribe". Il est presque toujours de la forme d'un 
lien de type "mailto" en HTML c'est à dire :

<mailto:[EMAIL PROTECTED]>

La plupart du temps, il suffit de trouver l'adresse email du compte spécifié dans cet 
en-tête et d'y envoyer un mail avec comme sujet "unsubscribe".

Cette solution n'est certes pas optimale puisqu'elle ne couvre pas l'exhaustivité des 
cas possibles (on rencontre notamment des en-tête de type liens HTML) mais a 
l'avantage de satisfaire la majorité des cas.

Quels sont les effets de ce patch dans mutt ?

Une nouvelle commande est présente, elle se nomme "list-unsubscribe" (par analogie 
avec "list-reply").

On y accède avec une pression de la touche 'X' dans le pager ou dans la visualisation 
d'un mail.

Lorsque cette commande est lancée, mutt cherche l'en-tête "List-Unsubscribe" et 
prépare un mail avec l'adresse trouvée dans cet en-tête et pré-renseigne le sujet du 
mail avec le mot "unsubscribe". Le contenu du mail sera quant à lui vide.

Que faire pour continuer ce patch ?

Ce patch est loin d'être terminé, il serait idéal qu'il remplisse les fonctionnalités 
suivantes :

    * ne pas mettre unsubscribe comme sujet mais bien utiliser la valeur de l'option 
"?subject=xxx" si celle-ci est présente.
    * être capable de gérer l'option "?body=xxx" de la même manière que "subject".
    * gérer les liens complexes, comme ceux disposant de plusieurs options séparées 
par des virgules.

Pour les gens motivés qui veulent tester ce patch non-officiel de mutt, voici le 
fichier contenant le diff unifié : mutt_list-unsubscribe.patch.txt (cf attachement).

Pour les gens un peu moins motivés mais curieux quand-même, voici un binaire compilé ( 
http://www.sukria.net/tarballs/mutt-unsubscribe.tar.gz ) pour les architectures i386 
sous Linux qui vous permettera de tester ce patch. 

-----------------------------------------------------------------------
http://www.sukria.net/content.php?id=94


Merci d'avance de vos commentaires :)

-- 

---------------------------------------------------------------------
* Alexis Sukrieh <[EMAIL PROTECTED]> 
* 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)

Répondre à