1 #include "config.h"
2 
3 #include <string.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 
7 #include "acctmgr-mod.h"
8 
9 /* PREUNSUB hook to check if user is subscribed */
HOOK_HANDLER(hook_preunsub_subscribed)10 HOOK_HANDLER(hook_preunsub_subscribed)
11 {
12     const char *fromaddy, *listname;
13     struct list_user user;
14 
15     /* Get our data */
16     fromaddy = LMAPI->get_string("subscribe-me");
17     listname = LMAPI->get_string("list");
18 
19     /* Sanity check */
20     if(!LMAPI->list_valid(listname)) {
21         LMAPI->nosuch(listname);
22         return HOOK_RESULT_FAIL;
23     }
24 
25     /* Check if user is on list */
26     if (!LMAPI->user_find_list(listname,fromaddy,&user)) {
27         if (LMAPI->get_bool("adminmode")) {
28             LMAPI->spit_status("User is not a member of that list.");
29             return HOOK_RESULT_FAIL;
30         } else {
31             LMAPI->spit_status("'Unsubscribe' request denied.");
32             LMAPI->result_printf("Your request was rejected for the following reason:\n\n");
33             LMAPI->result_printf("You are not on the list '%s'.\n\n",listname);
34         }
35         return HOOK_RESULT_FAIL;
36     }
37 
38     return HOOK_RESULT_OK;
39 }
40 
41 /* PREUNSUB hook to check if list is closed for unsubscribe */
HOOK_HANDLER(hook_preunsub_closed)42 HOOK_HANDLER(hook_preunsub_closed)
43 {
44     const char *unsubscribemode;
45     const char *fromaddy, *listname;
46     char buf[BIG_BUF];
47 
48     /* Admin mode is immune to this check */
49     if (LMAPI->get_bool("adminmode"))
50         return HOOK_RESULT_OK;
51 
52     unsubscribemode = LMAPI->get_var("unsubscribe-mode");
53 
54     if (!unsubscribemode)
55         unsubscribemode = LMAPI->get_var("subscribe-mode");
56 
57     fromaddy = LMAPI->get_string("subscribe-me");
58     listname = LMAPI->get_string("list");
59 
60     /* Check the mode */
61     if (strcasecmp(unsubscribemode,"closed") == 0) {
62        const char *adminaddy;
63        char cookie[BIG_BUF], cookiefile[SMALL_BUF];
64        char cmdbuf[BIG_BUF];
65        char *cmdptr;
66        char *listdir;
67 
68        adminaddy = LMAPI->get_var("administrivia-address");
69        if (!adminaddy) adminaddy = LMAPI->get_string("list-owner");
70 
71        listdir = LMAPI->list_directory(LMAPI->get_string("list"));
72        LMAPI->buffer_printf(cookiefile, sizeof(cookiefile) - 1, "%s/cookies",  listdir);
73 
74        LMAPI->set_var("cookie-for", LMAPI->get_string("list"), VAR_TEMP);
75 
76        /* Request our cookie */
77        if (!LMAPI->request_cookie(cookiefile,&cookie[0],'U',fromaddy)) {
78            LMAPI->spit_status("Unable to generate unsubscribe cookie!");
79            LMAPI->filesys_error(cookiefile);
80            return HOOK_RESULT_FAIL;
81        }
82        LMAPI->clean_var("cookie-for", VAR_TEMP);
83 
84        LMAPI->buffer_printf(buf, sizeof(buf) - 1, "Unsubscription request for '%s'", listname);
85        LMAPI->set_var("task-form-subject", buf, VAR_TEMP);
86 
87        /* ...and send the ticket to the admin */
88        if(!LMAPI->task_heading(adminaddy))
89            return HOOK_RESULT_FAIL;
90        LMAPI->smtp_body_text("# Unsubscription request received from ");
91        LMAPI->smtp_body_line(LMAPI->get_string("fromaddress"));
92        LMAPI->smtp_body_text("# for the address ");
93        LMAPI->smtp_body_text(fromaddy);
94        LMAPI->smtp_body_text(" and list ");
95        LMAPI->smtp_body_line(LMAPI->get_string("list"));
96        LMAPI->smtp_body_line("# ");
97        LMAPI->smtp_body_text("# To approve this, reply to this to ");
98        LMAPI->smtp_body_text(LMAPI->get_string("listserver-address"));
99        LMAPI->smtp_body_line(":");
100        LMAPI->smtp_body_line("// job");
101 
102        LMAPI->buffer_printf(cmdbuf, sizeof(cmdbuf) - 1, "appunsub %s %s %s",
103          LMAPI->get_string("list"), fromaddy, cookie);
104 
105        cmdptr = NULL;
106 
107        if (strlen(cmdbuf) > 60) {
108           cmdptr = strrchr(cmdbuf,' ');
109           *cmdptr++ = 0;
110        }
111 
112        LMAPI->smtp_body_text(cmdbuf);
113        if (cmdptr) {
114           LMAPI->smtp_body_line(" \\");
115           LMAPI->smtp_body_text(cmdptr);
116        }
117        LMAPI->smtp_body_line("");
118 
119        LMAPI->smtp_body_line("// eoj");
120 
121        /* With the original request if so desired */
122        if (LMAPI->get_bool("administrivia-include-requests")) {
123           FILE *infile;
124           char buffer[BIG_BUF];
125 
126           if ((infile = LMAPI->open_file(LMAPI->get_string("queuefile"),"r")) == NULL) {
127              LMAPI->log_printf(1,"Acctmgr unable to open queuefile to attach.\n");
128           } else {
129              LMAPI->smtp_body_line("\n-- Original Message --");
130 
131              while(LMAPI->read_file(buffer, sizeof(buffer), infile)) {
132                 LMAPI->smtp_body_text(buffer);
133              }
134              LMAPI->close_file(infile);
135           }
136        }
137 
138        LMAPI->task_ending();
139 
140        LMAPI->spit_status("List is closed-unsubscription, request has been forwarded to list admins.");
141 
142        return HOOK_RESULT_FAIL;
143     }
144 
145     return HOOK_RESULT_OK;
146 }
147 
148 /* PREUNSUB hook to check for confirm-mode unsubscribe */
HOOK_HANDLER(hook_preunsub_confirm)149 HOOK_HANDLER(hook_preunsub_confirm)
150 {
151     const char *unsubscribemode;
152     const char *fromaddy, *listname;
153 
154     if (LMAPI->get_bool("adminmode"))
155         return HOOK_RESULT_OK;
156 
157     unsubscribemode = LMAPI->get_var("unsubscribe-mode");
158 
159     /* Default to subscribe-mode if not set */
160     if (!unsubscribemode)
161         unsubscribemode = LMAPI->get_var("subscribe-mode");
162 
163     /* Get our data */
164     fromaddy = LMAPI->get_string("subscribe-me");
165     listname = LMAPI->get_string("list");
166 
167     /* Check mode equal to confirm, or the addresses not matching */
168     if ((strcasecmp(unsubscribemode,"confirm") == 0) ||
169        (strcasecmp(fromaddy,LMAPI->get_string("fromaddress")) &&
170        (!LMAPI->get_bool("adminmode")) &&
171        (strcasecmp(unsubscribemode,"open-auto") != 0)))
172     {
173        const char *adminaddy;
174        const char *sendas;
175        char cookie[BIG_BUF], cookiefile[BIG_BUF]; /* Changed cookiefile from SMALL_BUF to BIG_BUF due to listdir_file */
176        char cmdbuf[BIG_BUF];
177        char *cmdptr;
178 	   int unsub_confirm_file_included = 0;
179 
180        adminaddy = LMAPI->get_var("administrivia-address");
181        if (!adminaddy) adminaddy = LMAPI->get_string("list-owner");
182 
183        LMAPI->listdir_file(cookiefile, LMAPI->get_string("list"), "cookies");
184 
185        LMAPI->set_var("cookie-for", LMAPI->get_string("list"), VAR_TEMP);
186 
187        /* Request our cookie */
188        if (!LMAPI->request_cookie(cookiefile,&cookie[0],'U',fromaddy)) {
189            LMAPI->spit_status("Unable to generate unsubscribe cookie!");
190            LMAPI->filesys_error(cookiefile);
191            return HOOK_RESULT_FAIL;
192        }
193        LMAPI->clean_var("cookie-for", VAR_TEMP);
194 
195        /* Spit back the status */
196        LMAPI->spit_status("Subscription confirmation ticket sent to user being unsubscribed.");
197        sendas = LMAPI->get_var("send-as");
198 
199        /* And send the ticket */
200        if (!sendas) sendas = LMAPI->get_var("list-owner");
201        if (!sendas) sendas = LMAPI->get_var("listserver-address");
202        LMAPI->set_var("form-send-as", sendas, VAR_TEMP);
203        LMAPI->set_var("form-reply-to",
204 			   LMAPI->get_string("listserver-address"), VAR_TEMP);
205 	   LMAPI->set_var("task-form-subject",
206 			   LMAPI->get_string("unsubscribe-confirm-subject"), VAR_TEMP);
207 
208        if(!LMAPI->task_heading(fromaddy))
209            return HOOK_RESULT_FAIL;
210 
211 	   if(LMAPI->get_var("unsubscribe-confirm-file")) {
212 		   FILE *infile;
213 		   char tempfilename[BIG_BUF]; /* Changed from SMALL_BUF to BIG_BUF due to listdir_file */
214 		   LMAPI->listdir_file(tempfilename, LMAPI->get_string("list"),
215 				   LMAPI->get_string("unsubscribe-confirm-file"));
216 
217 		   if((infile = LMAPI->open_file(tempfilename, "r")) != NULL) {
218 			   char inputbuffer[BIG_BUF];
219 			   char linebuffer[BIG_BUF];
220 
221 			   LMAPI->smtp_body_line("# ");
222 			   while(LMAPI->read_file(inputbuffer, sizeof(inputbuffer), infile)) {
223 				   LMAPI->buffer_printf(linebuffer, sizeof(linebuffer) - 1, "# %s",
224 						   inputbuffer);
225 				   LMAPI->smtp_body_text(linebuffer);
226 			   }
227 			   LMAPI->smtp_body_line("# ");
228 			   LMAPI->close_file(infile);
229 
230 			   unsub_confirm_file_included = 1;
231 		   }
232 	   }
233 	   if(!unsub_confirm_file_included) {
234 		   LMAPI->smtp_body_text("# ");
235 		   LMAPI->smtp_body_text(LMAPI->get_string("fromaddress"));
236 		   LMAPI->smtp_body_line(" has requested that you be unsubscribed");
237 		   LMAPI->smtp_body_text("# from the ");
238 		   LMAPI->smtp_body_text(LMAPI->get_string("list"));
239 		   LMAPI->smtp_body_line(" mailing list.");
240 		   LMAPI->smtp_body_line("# To unsubscribe, reply to this message leaving the message body");
241 		   LMAPI->smtp_body_line("# intact, or send the following lines in e-mail to");
242 		   LMAPI->smtp_body_text(LMAPI->get_string("listserver-address"));
243 		   LMAPI->smtp_body_line(":\n");
244 	   }
245 	   LMAPI->smtp_body_line("// job");
246 
247        LMAPI->buffer_printf(cmdbuf, sizeof(cmdbuf) - 1, "appunsub %s %s %s",
248          LMAPI->get_string("list"), fromaddy, cookie);
249 
250        cmdptr = NULL;
251 
252        if (strlen(cmdbuf) > 60) {
253           cmdptr = strrchr(cmdbuf,' ');
254           *cmdptr++ = 0;
255        }
256 
257        LMAPI->smtp_body_text(cmdbuf);
258        if (cmdptr) {
259           LMAPI->smtp_body_line(" \\");
260           LMAPI->smtp_body_text(cmdptr);
261        }
262        LMAPI->smtp_body_line("");
263 
264        LMAPI->smtp_body_line("// eoj");
265        LMAPI->task_ending();
266        LMAPI->clean_var("form-send-as", VAR_TEMP);
267        LMAPI->clean_var("form-reply-to", VAR_TEMP);
268 	   LMAPI->clean_var("task-form-subject", VAR_TEMP);
269 
270     /* If we have prevent-second-message set, eat the PERsonal Results output for this session so far. */
271     if (LMAPI->get_bool("prevent-second-message")) {
272        char resultfile[BIG_BUF];
273 
274        LMAPI->buffer_printf(resultfile, sizeof(resultfile) - 1,
275             "%s.perr", LMAPI->get_string("queuefile"));
276 
277         LMAPI->unlink_file(resultfile);
278     }
279 
280        return HOOK_RESULT_FAIL;
281     }
282 
283     return HOOK_RESULT_OK;
284 }
285 
286 /* POSTUNSUB hook to send the welcome message */
HOOK_HANDLER(hook_postunsub_goodbye)287 HOOK_HANDLER(hook_postunsub_goodbye)
288 {
289     char outbuf[BIG_BUF];
290     const char *fromaddy, *listname;
291     char *listdir;
292     const char *adminnotice;
293 
294     /* If ADMIN, check if message should be sent */
295     if (LMAPI->get_bool("adminmode")) {
296         if (LMAPI->get_bool("admin-silent-subscribe"))
297             return HOOK_RESULT_OK;
298 
299         adminnotice = LMAPI->get_var("admin-unsubscribe-notice");
300         if ((strcasecmp(adminnotice, "silent") == 0) ||
301             (strcasecmp(adminnotice, "notify") == 0))
302             return HOOK_RESULT_OK;
303     }
304 
305     /* Get our data */
306     fromaddy = LMAPI->get_string("subscribe-me");
307     listname = LMAPI->get_string("list");
308 
309     /* Send the textfile.  Easy! */
310     listdir = LMAPI->list_directory(listname);
311     LMAPI->buffer_printf(outbuf, sizeof(outbuf) - 1, "%s/%s", listdir, LMAPI->get_string("goodbye-file"));
312     free(listdir);
313     LMAPI->set_var("task-form-subject",
314     	LMAPI->get_string("goodbye-subject"), VAR_TEMP);
315     LMAPI->send_textfile_expand(fromaddy,outbuf);
316     LMAPI->clean_var("task-form-subject", VAR_TEMP);
317 
318     if (LMAPI->exists_file(outbuf) && LMAPI->get_bool("prevent-second-message")) {
319        char resultfile[BIG_BUF];
320 
321        LMAPI->buffer_printf(resultfile, sizeof(resultfile) - 1,
322           "%s.perr", LMAPI->get_string("queuefile"));
323 
324        LMAPI->unlink_file(resultfile);
325     }
326 
327     return HOOK_RESULT_OK;
328 }
329 
330 /* POSTUNSUB hook for sending the administrivia */
HOOK_HANDLER(hook_postunsub_administrivia)331 HOOK_HANDLER(hook_postunsub_administrivia)
332 {
333     const char *fromaddy, *listname;
334 
335     /* Get our data */
336     fromaddy = LMAPI->get_string("subscribe-me");
337     listname = LMAPI->get_string("list");
338 
339     /* Make sure we're supposed to send */
340     if(!LMAPI->get_bool("no-administrivia")) {
341         const char *toaddy = NULL;
342 
343         toaddy = LMAPI->get_var("administrivia-address");
344         if (!toaddy && LMAPI->get_bool("owner-fallback"))
345            toaddy = LMAPI->get_var("list-owner");
346 
347         if(toaddy) {
348             char subject[SMALL_BUF];
349 
350             LMAPI->buffer_printf(subject, sizeof(subject) - 1, "%s unsubscribed from %s",
351                fromaddy, listname);
352 
353             /* Send the administrivia note */
354             LMAPI->set_var("task-form-subject",subject,VAR_TEMP);
355             if(!LMAPI->task_heading(toaddy))
356                 return HOOK_RESULT_FAIL;
357             LMAPI->smtp_body_text(fromaddy);
358             LMAPI->smtp_body_text(" unsubscribed from list ");
359             LMAPI->smtp_body_line(listname);
360             LMAPI->smtp_body_text("Command came from: ");
361             LMAPI->smtp_body_line(LMAPI->get_string("realsender"));
362 
363             /* And include the request, if so desired */
364             if (LMAPI->get_bool("administrivia-include-requests")) {
365                FILE *infile;
366 
367                if ((infile = LMAPI->open_file(LMAPI->get_string("queuefile"),"r")) != NULL) {
368                   char inbuffer[BIG_BUF];
369 
370                   LMAPI->smtp_body_line("\n-- Original Request --");
371                   while (LMAPI->read_file(inbuffer, sizeof(inbuffer), infile)) {
372                      LMAPI->smtp_body_text(inbuffer);
373                   }
374                   LMAPI->close_file(infile);
375                }
376             }
377             LMAPI->task_ending();
378         }
379     }
380 
381     return HOOK_RESULT_OK;
382 }
383 
384 /* 'unsubscribe' command */
CMD_HANDLER(cmd_unsubscribe)385 CMD_HANDLER(cmd_unsubscribe)
386 {
387     const char *listname = NULL;
388     char userfilepath[BIG_BUF];
389     struct list_user user;
390     const char *fromaddy;
391     char *listdir;
392     const char *adminnotice;
393 
394     fromaddy = LMAPI->get_string("fromaddress");
395     listname = LMAPI->get_var("list");
396 
397     /* Mode check */
398     if(params->num == 1) {
399         if(LMAPI->get_bool("adminmode")) {
400             /* Make sure it's an address if we're in admin mode */
401             if(strchr(params->words[0],'@')) {
402                fromaddy = params->words[0];
403             } else {
404                LMAPI->spit_status("Cannot provide a list in this context.");
405                return CMD_RESULT_CONTINUE;
406             }
407         } else {
408             if(strchr(params->words[0],'@')) {
409               fromaddy = params->words[0];
410             } else {
411               listname = params->words[0];
412             }
413         }
414     } else if (params->num == 2) {
415         if (LMAPI->get_bool("adminmode")) {
416            LMAPI->spit_status("Cannot provide a list in this context.");
417            return CMD_RESULT_CONTINUE;
418         }
419         listname = params->words[0];
420         fromaddy = params->words[1];
421     }
422 
423     /* Sanity check */
424     if(listname == NULL) {
425         LMAPI->spit_status("Does not appear to be a valid unsubscribe command.  No list in present context.  To see the lists available on this machine, send %s the command 'lists'.", SERVICE_NAME_MC);
426         return CMD_RESULT_CONTINUE;
427     }
428 
429     if(!LMAPI->set_context_list(listname)) {
430        LMAPI->nosuch(listname);
431        /* Return CMD_RESULT_END cause otherwise the list context
432         * might be incorrect for further changes
433         */
434         return CMD_RESULT_END;
435     }
436 
437     /* Sanity check */
438     if(!strchr(fromaddy,'@') || !strchr(fromaddy,'@')) {
439        LMAPI->spit_status("That doesn't appear to be a valid e-mail address.");
440        return CMD_RESULT_CONTINUE;
441     }
442 
443     /* Set up our data */
444     /* This needs to be VAR_GLOBAL to keep from being clobbered. */
445     LMAPI->set_var("subscribe-me",fromaddy,VAR_GLOBAL);
446 
447     /* Run PREUNSUB hooks */
448     if (LMAPI->do_hooks("PREUNSUB") == HOOK_RESULT_FAIL) {
449         return CMD_RESULT_CONTINUE;
450     }
451 
452     listdir = LMAPI->list_directory(LMAPI->get_string("list"));
453     LMAPI->buffer_printf(userfilepath, sizeof(userfilepath) - 1, "%s/users", listdir);
454     free(listdir);
455 
456     /* Make sure the address we unsubscribe is the correct one, in cases
457        where loose domain matching is enabled. */
458     if (!LMAPI->user_find_list(LMAPI->get_string("list"),fromaddy,&user)) {
459        LMAPI->spit_status("Error unsubscribing.");
460        return CMD_RESULT_CONTINUE;
461     }
462 
463     LMAPI->set_var("subscribe-me",user.address,VAR_GLOBAL);
464 
465     /* Remove user */
466     if (!LMAPI->user_remove(userfilepath,user.address)) {
467         char outbuf[BIG_BUF];
468 
469         LMAPI->log_printf(0, "%s unsubscribed from %s\n",user.address,listname);
470 
471         /* Send result note */
472         if (LMAPI->get_var("adminmode") || strcmp(fromaddy,LMAPI->get_string("fromaddress"))) {
473 
474             LMAPI->spit_status("Successfully unsubscribed.");
475 
476             adminnotice = LMAPI->get_var("admin-unsubscribe-notice");
477 
478             if (!LMAPI->get_bool("adminmode") ||
479                 (!LMAPI->get_bool("admin-silent-subscribe") &&
480                  !(strcasecmp(adminnotice, "silent") == 0) &&
481                  !(strcasecmp(adminnotice, "goodbye") == 0))) {
482 
483                LMAPI->buffer_printf(outbuf, sizeof(outbuf) - 1, "Unsubscribed from list '%s'", listname);
484                LMAPI->set_var("task-form-subject", outbuf, VAR_TEMP);
485 
486                if(!LMAPI->task_heading(fromaddy))
487                    return HOOK_RESULT_FAIL;
488 
489                if (!LMAPI->get_bool("adminmode") || LMAPI->get_bool("admin-actions-shown")) {
490                    LMAPI->smtp_body_text(">> (Unsubscribed from list by ");
491                    LMAPI->smtp_body_text(LMAPI->get_var("realsender"));
492                    LMAPI->smtp_body_line(")");
493                }
494                LMAPI->quote_command();
495                LMAPI->buffer_printf(outbuf, sizeof(outbuf) - 1, "You have been removed from list '%s'", listname);
496                LMAPI->smtp_body_line(&outbuf[0]);
497                LMAPI->task_ending();
498             }
499         } else {
500             LMAPI->spit_status("Unsubscribed.");
501         }
502 
503         /* Do POSTUNSUB hooks */
504         (void)LMAPI->do_hooks("POSTUNSUB");
505 
506         return CMD_RESULT_CONTINUE;
507     } else {
508         LMAPI->filesys_error(&userfilepath[0]);
509         return CMD_RESULT_END;
510     }
511     return CMD_RESULT_CONTINUE;
512 }
513 
514 /* 'appunsub' command */
CMD_HANDLER(cmd_appunsub)515 CMD_HANDLER(cmd_appunsub)
516 {
517    /* Sanity check */
518    if (params->num != 3) {
519       LMAPI->spit_status("Invalid number of parameters.");
520       return CMD_RESULT_CONTINUE;
521    } else {
522       struct list_user user;
523       const char *fromaddy;
524       char filename[SMALL_BUF], buffer[BIG_BUF]; /* buffer changed from 256(SMALL_BUF) to BIG_BUF due to verify_cookie */
525       int isadmin;
526       char *listdir;
527 
528       isadmin = 0;
529 
530       /* Set list context */
531       if (!LMAPI->set_context_list(params->words[0])) {
532          LMAPI->spit_status("Invalid list.");
533          return CMD_RESULT_CONTINUE;
534       }
535 
536       /* Check if we're admin or not */
537       if (LMAPI->user_find_list(params->words[0],LMAPI->get_string("realsender"),&user)) {
538          if (LMAPI->user_hasflag(&user,"ADMIN")) {
539             fromaddy = params->words[1]; isadmin=1;
540          } else {
541             fromaddy = params->words[1];
542          }
543       } else fromaddy = params->words[1];
544 
545       listdir = LMAPI->list_directory(params->words[0]);
546       LMAPI->buffer_printf(filename, sizeof(filename) - 1, "%s/cookies", listdir);
547 
548       /* Verify cookie exists */
549       if (LMAPI->verify_cookie(filename,params->words[2],'U', &buffer[0])) {
550         /* Verify cookie data matches */
551         if(LMAPI->match_cookie(params->words[2],LMAPI->get_string("list"))) {
552            struct list_user user;
553 
554            LMAPI->del_cookie(filename,params->words[2]);
555            listdir = LMAPI->list_directory(params->words[0]);
556            LMAPI->buffer_printf(filename, sizeof(filename) - 1, "%s/users", listdir);
557            free(listdir);
558 
559            if (!LMAPI->user_find_list(params->words[0],
560              fromaddy, &user)) {
561               LMAPI->spit_status("Error unsubscribing; user is no longer on list.");
562               return CMD_RESULT_CONTINUE;
563            }
564 
565            /* Remove the user */
566            if (!LMAPI->user_remove(filename,fromaddy)) {
567                char outbuf[BIG_BUF];
568 
569                LMAPI->log_printf(0, "%s unsubscribed from %s\n",fromaddy,params->words[0]);
570 
571                /* Send note */
572                if (isadmin) {
573                    LMAPI->buffer_printf(outbuf, sizeof(outbuf) - 1, "Unsubscribed from list '%s'", params->words[0]);
574                    LMAPI->set_var("task-form-subject", outbuf, VAR_TEMP);
575 
576                    LMAPI->spit_status("Successfully unsubscribed.");
577                    if(!LMAPI->task_heading(fromaddy))
578                        return HOOK_RESULT_FAIL;
579                    LMAPI->smtp_body_text(">> (unsubscribed from list by ");
580                    LMAPI->smtp_body_text(LMAPI->get_var("realsender"));
581                    LMAPI->smtp_body_line(")");
582                    LMAPI->quote_command();
583                    LMAPI->buffer_printf(outbuf, sizeof(outbuf) - 1, "You have been removed from list '%s'", params->words[0]);
584                    LMAPI->smtp_body_line(&outbuf[0]);
585                    LMAPI->task_ending();
586                } else {
587                    LMAPI->spit_status("Unsubscribed.");
588                }
589 
590                /* Do POSTUNSUB hooks */
591 
592                LMAPI->set_var("subscribe-me",user.address,VAR_GLOBAL);
593                (void)LMAPI->do_hooks("POSTUNSUB");
594                return CMD_RESULT_CONTINUE;
595            } else {
596                LMAPI->filesys_error(&filename[0]);
597                return CMD_RESULT_END;
598            }
599         } else {
600            LMAPI->spit_status("Cookie cannot be used from this address.");
601            return CMD_RESULT_CONTINUE;
602         }
603       } else {
604         LMAPI->spit_status("No such cookie or else cookie is of wrong type.");
605         return CMD_RESULT_CONTINUE;
606       }
607    }
608    return CMD_RESULT_CONTINUE;
609 }
610