summaryrefslogtreecommitdiffabout
path: root/src/mail.c
Unidiff
Diffstat (limited to 'src/mail.c') (more/less context) (ignore whitespace changes)
-rw-r--r--src/mail.c244
1 files changed, 222 insertions, 22 deletions
diff --git a/src/mail.c b/src/mail.c
index 91ea502..15c2937 100644
--- a/src/mail.c
+++ b/src/mail.c
@@ -17,6 +17,7 @@
17#include "wydawca.h" 17#include "wydawca.h"
18#include <mail.h> 18#include <mail.h>
19#include <hash.h> 19#include <hash.h>
20#include <gpgme.h>
20 21
21int mailer_opened; 22int mailer_opened;
22mu_mailer_t mailer; 23mu_mailer_t mailer;
@@ -27,6 +28,7 @@ unsigned long owner_notification_flags;
27char *user_message_template[MAX_EVENT]; 28char *user_message_template[MAX_EVENT];
28 29
29char *admin_stat_message; 30char *admin_stat_message;
31char *admin_stat_sign_key;
30 32
31void 33void
32mail_init () 34mail_init ()
@@ -44,8 +46,203 @@ mail_init ()
44 } 46 }
45} 47}
46 48
49struct mu_stream_handle
50{
51 mu_stream_t str;
52 mu_off_t off;
53};
54
55static ssize_t
56mu_stream_data_read_cb (void *handle, void *buffer, size_t size)
57{
58 struct mu_stream_handle *mhp = handle;
59 size_t nread;
60 int rc;
61
62 rc = mu_stream_read (mhp->str, buffer, size, mhp->off, &nread);
63 if (rc)
64 {
65 logmsg (LOG_ERR, "mu_stream_read: %s", mu_strerror (rc));
66 errno = EIO;
67 return -1;
68 }
69
70 mhp->off += nread;
71 return nread;
72}
73
74static int
75gpg_sign (gpgme_data_t *output, gpgme_data_t input, const char *sign_keys)
76{
77 gpgme_ctx_t ctx;
78 gpgme_error_t err = 0;
79 gpgme_key_t key;
80
81 err = gpgme_new (&ctx);
82 if (err)
83 {
84 logmsg (LOG_ERR, _("GPGME: cannot create context: %s"),
85 gpgme_strerror (err));
86 return 1;
87 }
88
89 err = gpgme_op_keylist_start (ctx, sign_keys, 0);
90 if (!err)
91 {
92 while ((err = gpgme_op_keylist_next (ctx, &key)) == 0)
93 {
94 err = gpgme_signers_add (ctx, key);
95 gpgme_key_release (key);
96 }
97 }
98
99 if (err && gpg_err_code (err) != GPG_ERR_EOF)
100 {
101 logmsg (LOG_ERR, _("GPGME: cannot list keys: %s"),
102 gpgme_strerror (err));
103 gpgme_release (ctx);
104 return 1;
105 }
106
107 err = gpgme_data_new (output);
108 if (err)
109 {
110 logmsg (LOG_ERR, _("%s: GPGME error: %s"),
111 "gpgme_data_new",
112 gpgme_strerror (err));
113 gpgme_release (ctx);
114 return 1;
115 }
116
117 /* FIXME: Passphrase */
118 gpgme_set_textmode (ctx, 1);
119 gpgme_set_armor (ctx, 1);
120
121 err = gpgme_op_sign (ctx, input, *output, GPGME_SIG_MODE_CLEAR);
122 if (err)
123 logmsg (LOG_ERR, _("%s: GPGME error: %s"),
124 "gpgme_op_sign",
125 gpgme_strerror (err));
126#if 0
127 /* FIXME: */
128 else if (debug_level > 1)
129 gpgme_debug_info (ctx);
130#endif
131
132 gpgme_release (ctx);
133 return err != 0;
134}
135
136static int
137sign_message (mu_message_t *pmsg, const char *key)
138{
139 mu_message_t msg = *pmsg;
140 mu_message_t newmsg;
141 mu_body_t body;
142 mu_header_t hdr;
143 struct mu_stream_handle mhn;
144 mu_stream_t istr, ostr;
145 int rc;
146 struct gpgme_data_cbs cbs;
147 gpgme_data_t input, output;
148 gpgme_error_t err;
149 char *buf = NULL;
150 size_t size = 0;
151 size_t nread;
152
153 if (debug_level)
154 logmsg (LOG_DEBUG, _("signing message as %s"), key);
155
156 if (wydawca_gpg_homedir)
157 {
158 if (debug_level > 1)
159 logmsg (LOG_DEBUG, _("setting GNUPG home directory: %s"),
160 wydawca_gpg_homedir);
161 setenv ("GNUPGHOME", wydawca_gpg_homedir, 1);
162 }
163
164 if ((rc = mu_message_get_body (msg, &body)))
165 {
166 logmsg (LOG_ERR, "mu_message_get_body: %s", mu_strerror (rc));
167 return 1;
168 }
169
170 if ((rc = mu_body_get_stream (body, &mhn.str)))
171 {
172 logmsg (LOG_ERR, "mu_message_get_stream: %s", mu_strerror (rc));
173 return 1;
174 }
175
176 mu_stream_seek (mhn.str, 0, SEEK_SET);
177 mhn.off = 0;
178
179 memset (&cbs, 0, sizeof (cbs));
180 cbs.read = mu_stream_data_read_cb;
181
182 err = gpgme_data_new_from_cbs (&input, &cbs, &mhn);
183 if (err)
184 {
185 logmsg (LOG_ERR, "gpgme_data_new_from_cbs: %s",
186 gpgme_strerror (rc));
187 return 1;
188 }
189
190 rc = gpg_sign (&output, input, key);
191
192 if (gpgme_data_seek (output, 0, SEEK_SET) == -1)
193 {
194 logmsg (LOG_ERR, "gpgme_data_seek: %s", strerror (errno));
195 return 1;
196 }
197
198 mu_message_create (&newmsg, NULL);
199 mu_message_get_stream (newmsg, &ostr);
200
201 /* Copy headers */
202 mu_message_get_header (msg, &hdr);
203 mu_header_get_stream (hdr, &istr);
204 mu_stream_seek (istr, 0, SEEK_SET);
205 while ((rc = mu_stream_sequential_getline (istr, &buf, &size, &nread)) == 0
206 && nread)
207 {
208 rc = mu_stream_sequential_write (ostr, buf, nread);
209 if (rc)
210 {
211 logmsg (LOG_ERR, "mu_stream_sequential_write: %s",
212 mu_strerror (rc));
213 break;
214 }
215 }
216
217 if (rc == 0)
218 {
219 while ((nread = gpgme_data_read (output, buf, size)) > 0)
220 {
221 rc = mu_stream_sequential_write (ostr, buf, nread);
222 if (rc)
223 {
224 logmsg (LOG_ERR, "mu_stream_sequential_write: %s",
225 mu_strerror (rc));
226 break;
227 }
228 }
229
230 if (rc == 0)
231 {
232 mu_message_destroy (&msg, mu_message_get_owner (msg));
233 *pmsg = newmsg;
234 }
235 }
236
237 gpgme_data_release (output);
238 free (buf);
239
240 return rc;
241}
242
47void 243void
48mail_send_message (mu_address_t rcpt, const char *text) 244mail_send_message (mu_address_t rcpt, const char *text,
245 const char *signer_key)
49{ 246{
50 int rc; 247 int rc;
51 mu_message_t msg; 248 mu_message_t msg;
@@ -91,7 +288,7 @@ mail_send_message (mu_address_t rcpt, const char *text)
91 if (debug_level > 2) 288 if (debug_level > 2)
92 mailer_flags = MAILER_FLAG_DEBUG_DATA; 289 mailer_flags = MAILER_FLAG_DEBUG_DATA;
93 } 290 }
94 291
95 if (!mailer_opened) 292 if (!mailer_opened)
96 { 293 {
97 if ((rc = mu_mailer_open (mailer, mailer_flags))) 294 if ((rc = mu_mailer_open (mailer, mailer_flags)))
@@ -106,10 +303,16 @@ mail_send_message (mu_address_t rcpt, const char *text)
106 mailer_opened = 1; 303 mailer_opened = 1;
107 } 304 }
108 305
109 rc = mu_mailer_send_message (mailer, msg, from_address, rcpt); 306 if (signer_key)
110 if (rc) 307 sign_message (&msg, signer_key);
111 logmsg (LOG_CRIT, _("cannot send message: %s"), mu_strerror (rc)); 308
112 309 if (!dry_run_mode)
310 {
311 rc = mu_mailer_send_message (mailer, msg, from_address, rcpt);
312 if (rc)
313 logmsg (LOG_CRIT, _("cannot send message: %s"), mu_strerror (rc));
314 }
315
113 mu_message_destroy (&msg, mu_message_get_owner (msg)); 316 mu_message_destroy (&msg, mu_message_get_owner (msg));
114} 317}
115 318
@@ -244,9 +447,6 @@ mail_stats ()
244 free (buf); 447 free (buf);
245 } 448 }
246 449
247 if (dry_run_mode)
248 return;
249
250 tc = timer_get_count () * 3; 450 tc = timer_get_count () * 3;
251 exp = make_stat_expansion (tc + 1); 451 exp = make_stat_expansion (tc + 1);
252 time (&t); 452 time (&t);
@@ -264,7 +464,7 @@ mail_stats ()
264 } 464 }
265 text = meta_expand_string (tmpl, exp, NULL, NULL, NULL); 465 text = meta_expand_string (tmpl, exp, NULL, NULL, NULL);
266 466
267 mail_send_message (admin_address, text); 467 mail_send_message (admin_address, text, admin_stat_sign_key);
268 468
269 free (text); 469 free (text);
270 meta_free (exp); 470 meta_free (exp);
@@ -366,6 +566,8 @@ do_notify (struct file_triplet *trp, enum notification_event ev,
366{ 566{
367 mu_address_t rcpt = NULL; 567 mu_address_t rcpt = NULL;
368 const char *errp; 568 const char *errp;
569 const char *msg;
570
369 switch (ntf->tgt) 571 switch (ntf->tgt)
370 { 572 {
371 case notify_read: 573 case notify_read:
@@ -408,21 +610,19 @@ do_notify (struct file_triplet *trp, enum notification_event ev,
408 free (buf); 610 free (buf);
409 } 611 }
410 else 612 else
411 logmsg (LOG_DEBUG, _("notifying message recipients (project %s) about %s"), 613 logmsg (LOG_DEBUG,
614 _("notifying message recipients (project %s) about %s"),
412 trp->project, notification_event_str (ev)); 615 trp->project, notification_event_str (ev));
413 } 616 }
414 617
415 if (!dry_run_mode) 618 msg = resolve_message_template (ntf->msg);
619 if (!msg)
620 logmsg (LOG_ERR, _("undefined message reference: %s"), ntf->msg);
621 else
416 { 622 {
417 const char *msg = resolve_message_template (ntf->msg); 623 char *text = triplet_expand_param (msg, trp);
418 if (!msg) 624 mail_send_message (rcpt, text, ntf->sign_keys);
419 logmsg (LOG_ERR, _("undefined message reference: %s"), ntf->msg); 625 free (text);
420 else
421 {
422 char *text = triplet_expand_param (msg, trp);
423 mail_send_message (rcpt, text);
424 free (text);
425 }
426 } 626 }
427 627
428 mu_address_destroy (&rcpt); 628 mu_address_destroy (&rcpt);

Return to:

Send suggestions and report system problems to the System administrator.