1 /* GNU Mailutils -- a suite of utilities for electronic mail
2    Copyright (C) 1999-2021 Free Software Foundation, Inc.
3 
4    GNU Mailutils is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3, or (at your option)
7    any later version.
8 
9    GNU Mailutils is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
16 
17 #include "mail.h"
18 
19 /*
20  * q[uit]
21  * <EOF>
22  */
23 
24 int
mail_quit(int argc MU_ARG_UNUSED,char ** argv MU_ARG_UNUSED)25 mail_quit (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
26 {
27   if (mail_mbox_close ())
28     return 1;
29   exit (0);
30 }
31 
32 int
mail_mbox_close(void)33 mail_mbox_close (void)
34 {
35   mu_url_t url = NULL;
36   size_t held_count = 0;
37 
38   if (!mbox)
39     return 0;
40 
41   if (!mailvar_is_true (mailvar_name_readonly))
42     {
43       if (mail_mbox_commit ())
44 	return 1;
45 
46       mu_mailbox_flush (mbox, 1);
47     }
48 
49   mu_mailbox_get_url (mbox, &url);
50   mu_mailbox_messages_count (mbox, &held_count);
51   mu_printf (
52            ngettext ("Held %lu message in %s\n",
53                      "Held %lu messages in %s\n",
54                      held_count),
55            (unsigned long) held_count, util_url_to_string (url));
56   mu_mailbox_close (mbox);
57   mu_mailbox_destroy (&mbox);
58   return 0;
59 }
60 
61 enum mailbox_class
62   {
63     MBX_SYSTEM,
64     MBX_MBOX,
65     MBX_USER
66   };
67 
68 static enum mailbox_class
mailbox_classify(void)69 mailbox_classify (void)
70 {
71   mu_url_t url;
72 
73   mu_mailbox_get_url (mbox, &url);
74   if (strcmp (util_url_to_string (url), getenv ("MBOX")) == 0)
75     return MBX_MBOX;
76   else
77     {
78       mu_mailbox_t mb;
79       mu_url_t u;
80       mu_mailbox_create_default (&mb, NULL);
81       mu_mailbox_get_url (mb, &u);
82       if (strcmp (mu_url_to_string (u), mu_url_to_string (url)) == 0)
83 	return MBX_SYSTEM;
84     }
85 
86   return MBX_USER;
87 }
88 
89 int
mail_mbox_commit(void)90 mail_mbox_commit (void)
91 {
92   unsigned int i;
93   mu_mailbox_t dest_mbox = NULL;
94   int saved_count = 0;
95   mu_message_t msg;
96   mu_attribute_t attr;
97   int keepsave = mailvar_is_true (mailvar_name_keepsave);
98   int hold = mailvar_is_true (mailvar_name_hold);
99 
100   enum mailbox_class class = mailbox_classify ();
101   if (class != MBX_SYSTEM)
102     {
103       /* The mailbox we are closing is not a system one (%). Stay on the
104 	 safe side: retain both read and saved messages in the mailbox. */
105       hold = 1;
106       keepsave = 1;
107     }
108 
109   for (i = 1; i <= total; i++)
110     {
111       int status;
112       enum { ACT_KEEP, ACT_MBOX, ACT_DELETE } action = ACT_KEEP;
113 
114       if (util_get_message (mbox, i, &msg))
115 	return 1;
116 
117       mu_message_get_attribute (msg, &attr);
118       if (mu_attribute_is_deleted (attr))
119 	continue;
120 
121       if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_PRESERVED))
122 	action = ACT_KEEP;
123       else if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_MBOXED))
124 	action = ACT_MBOX;
125       else if (class == MBX_SYSTEM)
126 	{
127 	  if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_SHOWN
128 					      | MAIL_ATTRIBUTE_TOUCHED))
129 	    action = hold ? ACT_KEEP : ACT_MBOX;
130 	  else if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_SAVED))
131 	    {
132 	      if (keepsave)
133 		action = hold ? ACT_KEEP : ACT_MBOX;
134 	      else
135 		action = ACT_DELETE;
136 	    }
137 	}
138 
139       switch (action)
140 	{
141 	case ACT_KEEP:
142 	  if (mu_attribute_is_read (attr))
143 	    mu_attribute_set_seen (attr);
144 	  break;
145 
146 	case ACT_MBOX:
147 	  if (!dest_mbox)
148 	    {
149 	      char *name = getenv ("MBOX");
150 
151 	      if ((status = mu_mailbox_create_default (&dest_mbox, name)) != 0)
152 		{
153 		  mu_error (_("Cannot create mailbox %s: %s"), name,
154                               mu_strerror (status));
155 		  return 1;
156 		}
157               if ((status = mu_mailbox_open (dest_mbox,
158 					     MU_STREAM_WRITE | MU_STREAM_CREAT))
159 		  != 0)
160 		{
161 		  mu_error (_("Cannot open mailbox %s: %s"), name,
162                               mu_strerror (status));
163 		  return 1;
164 		}
165 	    }
166 
167 	  status = mu_mailbox_append_message (dest_mbox, msg);
168 	  if (status)
169 	    {
170 	      mu_url_t url = NULL;
171 	      mu_mailbox_get_url (dest_mbox, &url);
172 	      mu_error (_("Cannot append message to %s: %s"),
173 			util_url_to_string (url),
174 			mu_strerror (status));
175 	    }
176 	  else
177 	    {
178 	      mu_attribute_set_deleted (attr);
179 	      saved_count++;
180 	    }
181 	  break;
182 
183 	case ACT_DELETE:
184 	  mu_attribute_set_deleted (attr);
185 	  break;
186 	}
187     }
188 
189   if (saved_count)
190     {
191       mu_url_t u = NULL;
192 
193       mu_mailbox_get_url (dest_mbox, &u);
194       mu_printf (
195               ngettext ("Saved %d message in %s\n",
196                         "Saved %d messages in %s\n",
197 			saved_count),
198               saved_count, util_url_to_string (u));
199       mu_mailbox_close (dest_mbox);
200       mu_mailbox_destroy (&dest_mbox);
201     }
202   return 0;
203 }
204