citadel
About: Citadel is an advanced messaging and collaboration system for groupware and BBS applications (preferred OS: Linux).
  Fossies Dox: citadel.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

Loading...
Searching...
No Matches
journaling.c
Go to the documentation of this file.
1// Message journaling functions.
2//
3// Copyright (c) 1987-2022 by the citadel.org team
4//
5// This program is open source software. Use, duplication, or disclosure
6// is subject to the terms of the GNU General Public License, version 3.
7
8#include <stdio.h>
9#include <libcitadel.h>
10#include "ctdl_module.h"
11#include "citserver.h"
12#include "config.h"
13#include "user_ops.h"
14#include "serv_vcard.h" // Needed for vcard_getuser and extract_inet_email_addrs
15#include "internet_addressing.h"
16#include "journaling.h"
17
18struct jnlq *jnlq = NULL; // journal queue
19
20/*
21 * Hand off a copy of a message to be journalized.
22 */
24 StrBuf *saved_rfc822_version,
25 struct recptypes *recps) {
26
27 struct jnlq *jptr = NULL;
28
29 /* Avoid double journaling! */
30 if (!CM_IsEmpty(msg, eJournal)) {
31 FreeStrBuf(&saved_rfc822_version);
32 return;
33 }
34
35 jptr = (struct jnlq *)malloc(sizeof(struct jnlq));
36 if (jptr == NULL) {
37 FreeStrBuf(&saved_rfc822_version);
38 return;
39 }
40 memset(jptr, 0, sizeof(struct jnlq));
41 if (recps != NULL) memcpy(&jptr->recps, recps, sizeof(struct recptypes));
42 if (!CM_IsEmpty(msg, eAuthor)) jptr->from = strdup(msg->cm_fields[eAuthor]);
43 if (!CM_IsEmpty(msg, erFc822Addr)) jptr->rfca = strdup(msg->cm_fields[erFc822Addr]);
44 if (!CM_IsEmpty(msg, eMsgSubject)) jptr->subj = strdup(msg->cm_fields[eMsgSubject]);
45 if (!CM_IsEmpty(msg, emessageId)) jptr->msgn = strdup(msg->cm_fields[emessageId]);
46 jptr->rfc822 = SmashStrBuf(&saved_rfc822_version);
47
48 /* Add to the queue */
50 jptr->next = jnlq;
51 jnlq = jptr;
53}
54
55
56/*
57 * Convert a local user name to an internet email address for the journal
58 * FIXME - grab the user's Internet email address from the user record, not from vCard !!!!
59 */
60void local_to_inetemail(char *inetemail, char *localuser, size_t inetemail_len) {
61 struct ctdluser us;
62 struct vCard *v;
63
64 strcpy(inetemail, "");
65 if (CtdlGetUser(&us, localuser) != 0) {
66 return;
67 }
68
69 v = vcard_get_user(&us);
70 if (v == NULL) {
71 return;
72 }
73
74 extract_inet_email_addrs(inetemail, inetemail_len, NULL, 0, v, 1);
75 vcard_free(v);
76}
77
78
79/*
80 * Called by JournalRunQueue() to send an individual message.
81 */
82void JournalRunQueueMsg(struct jnlq *jmsg) {
83
84 struct CtdlMessage *journal_msg = NULL;
85 struct recptypes *journal_recps = NULL;
86 StrBuf *message_text = NULL;
87 char mime_boundary[256];
88 long mblen;
89 long rfc822len;
90 char recipient[256];
91 char inetemail[256];
92 static int seq = 0;
93 int i;
94
95 if (jmsg == NULL)
96 return;
97 journal_recps = validate_recipients(CtdlGetConfigStr("c_journal_dest"), NULL, 0);
98 if (journal_recps != NULL) {
99
100 if ( (journal_recps->num_local > 0)
101 || (journal_recps->num_internet > 0)
102 || (journal_recps->num_room > 0)
103 ) {
104
105 /*
106 * Construct journal message.
107 * Note that we are transferring ownership of some of the memory here.
108 */
109 journal_msg = malloc(sizeof(struct CtdlMessage));
110 memset(journal_msg, 0, sizeof(struct CtdlMessage));
111 journal_msg->cm_magic = CTDLMESSAGE_MAGIC;
112 journal_msg->cm_anon_type = MES_NORMAL;
113 journal_msg->cm_format_type = FMT_RFC822;
114 CM_SetField(journal_msg, eJournal, HKEY("is journal"));
115
116 if (!IsEmptyStr(jmsg->from)) {
117 CM_SetField(journal_msg, eAuthor, jmsg->from, -1);
118 }
119
120 if (!IsEmptyStr(jmsg->rfca)) {
121 CM_SetField(journal_msg, erFc822Addr, jmsg->rfca, -1);
122 }
123
124 if (!IsEmptyStr(jmsg->subj)) {
125 CM_SetField(journal_msg, eMsgSubject, jmsg->subj, -1);
126 }
127
128 mblen = snprintf(mime_boundary, sizeof(mime_boundary),
129 "--Citadel-Journal-%08lx-%04x--", time(NULL), ++seq);
130
131 if (!IsEmptyStr(jmsg->rfc822)) {
132 rfc822len = strlen(jmsg->rfc822);
133 }
134 else {
135 rfc822len = 0;
136 }
137
138 message_text = NewStrBufPlain(NULL, rfc822len + sizeof(struct recptypes) + 1024);
139
140 /*
141 * Here is where we begin to compose the journalized message.
142 * (The "ExJournalReport" header is consumed by some email retention services which assume the journaling agent is Exchange.)
143 */
144 StrBufAppendBufPlain(
145 message_text,
146 HKEY("Content-type: multipart/mixed; boundary=\""),
147 0
148 );
149
150 StrBufAppendBufPlain(message_text, mime_boundary, mblen, 0);
151
152 StrBufAppendBufPlain(
153 message_text,
154 HKEY("\"\r\n"
155 "Content-Identifier: ExJournalReport\r\n"
156 "MIME-Version: 1.0\r\n"
157 "\n"
158 "--"),
159 0
160 );
161
162 StrBufAppendBufPlain(message_text, mime_boundary, mblen, 0);
163
164 StrBufAppendBufPlain(
165 message_text,
166 HKEY("\r\n"
167 "Content-type: text/plain\r\n"
168 "\r\n"
169 "Sender: "), 0);
170
171 if (CM_IsEmpty(journal_msg, eAuthor))
172 StrBufAppendBufPlain(
173 message_text,
174 journal_msg->cm_fields[eAuthor], -1, 0);
175 else
176 StrBufAppendBufPlain(
177 message_text,
178 HKEY("(null)"), 0);
179
180 if (!CM_IsEmpty(journal_msg, erFc822Addr)) {
181 StrBufAppendPrintf(message_text, " <%s>",
182 journal_msg->cm_fields[erFc822Addr]);
183 }
184
185 StrBufAppendBufPlain(message_text, HKEY("\r\nMessage-ID: <"), 0);
186 StrBufAppendBufPlain(message_text, jmsg->msgn, -1, 0);
187 StrBufAppendBufPlain(message_text, HKEY(">\r\nRecipients:\r\n"), 0);
188
189 if (jmsg->recps.num_local > 0) {
190 for (i=0; i<jmsg->recps.num_local; ++i) {
191 extract_token(recipient, jmsg->recps.recp_local, i, '|', sizeof recipient);
192 local_to_inetemail(inetemail, recipient, sizeof inetemail);
193 StrBufAppendPrintf(message_text, " %s <%s>\r\n", recipient, inetemail);
194 }
195 }
196
197 if (jmsg->recps.num_internet > 0) {
198 for (i=0; i<jmsg->recps.num_internet; ++i) {
199 extract_token(recipient, jmsg->recps.recp_internet, i, '|', sizeof recipient);
200 StrBufAppendPrintf(message_text, " %s\r\n", recipient);
201 }
202 }
203
204 StrBufAppendBufPlain(message_text, HKEY("\r\n" "--"), 0);
205 StrBufAppendBufPlain(message_text, mime_boundary, mblen, 0);
206 StrBufAppendBufPlain(message_text, HKEY("\r\nContent-type: message/rfc822\r\n\r\n"), 0);
207 StrBufAppendBufPlain(message_text, jmsg->rfc822, rfc822len, 0);
208 StrBufAppendBufPlain(message_text, HKEY("--"), 0);
209 StrBufAppendBufPlain(message_text, mime_boundary, mblen, 0);
210 StrBufAppendBufPlain(message_text, HKEY("--\r\n"), 0);
211
212 CM_SetAsFieldSB(journal_msg, eMesageText, &message_text);
213 free(jmsg->rfc822);
214 free(jmsg->msgn);
215 jmsg->rfc822 = NULL;
216 jmsg->msgn = NULL;
217
218 /* Submit journal message */
219 CtdlSubmitMsg(journal_msg, journal_recps, "");
220 CM_Free(journal_msg);
221 }
222
223 free_recipients(journal_recps);
224 }
225
226 /* We are responsible for freeing this memory. */
227 free(jmsg);
228}
229
230
231/*
232 * Run the queue.
233 */
234void JournalRunQueue(void) {
235 struct jnlq *jptr = NULL;
236
237 while (jnlq != NULL) {
239 if (jnlq != NULL) {
240 jptr = jnlq;
241 jnlq = jnlq->next;
242 }
244 JournalRunQueueMsg(jptr);
245 }
246}
#define MES_NORMAL
Definition: citadel.h:118
char * CtdlGetConfigStr(char *key)
Definition: config.c:363
int CtdlGetUser(struct ctdluser *usbuf, char *name)
Definition: user_ops.c:64
struct recptypes * validate_recipients(char *supplied_recipients, const char *RemoteIdentifier, int Flags)
void free_recipients(struct recptypes *valid)
void JournalBackgroundSubmit(struct CtdlMessage *msg, StrBuf *saved_rfc822_version, struct recptypes *recps)
Definition: journaling.c:23
void JournalRunQueueMsg(struct jnlq *jmsg)
Definition: journaling.c:82
struct jnlq * jnlq
Definition: journaling.c:18
void local_to_inetemail(char *inetemail, char *localuser, size_t inetemail_len)
Definition: journaling.c:60
void JournalRunQueue(void)
Definition: journaling.c:234
void CM_Free(struct CtdlMessage *msg)
Definition: msgbase.c:305
int CM_IsEmpty(struct CtdlMessage *Msg, eMsgField which)
Definition: msgbase.c:132
long CtdlSubmitMsg(struct CtdlMessage *msg, struct recptypes *recps, const char *force)
Definition: msgbase.c:2588
void CM_SetField(struct CtdlMessage *Msg, eMsgField which, const char *buf, long length)
Definition: msgbase.c:137
void CM_SetAsFieldSB(struct CtdlMessage *Msg, eMsgField which, StrBuf **buf)
Definition: msgbase.c:253
void * malloc(unsigned)
void free(void *)
struct vCard * vcard_get_user(struct ctdluser *u)
Definition: serv_vcard.c:477
void extract_inet_email_addrs(char *emailaddrbuf, size_t emailaddrbuf_len, char *secemailaddrbuf, size_t secemailaddrbuf_len, struct vCard *v, int local_addrs_only)
Definition: serv_vcard.c:82
#define CTDLMESSAGE_MAGIC
Definition: server.h:42
@ emessageId
Definition: server.h:311
@ eMesageText
Definition: server.h:315
@ erFc822Addr
Definition: server.h:310
@ eAuthor
Definition: server.h:307
@ eMsgSubject
Definition: server.h:320
@ eJournal
Definition: server.h:312
#define FMT_RFC822
Definition: server.h:178
@ S_JOURNAL_QUEUE
Definition: server.h:148
int cm_magic
Definition: server.h:34
char cm_anon_type
Definition: server.h:35
char * cm_fields[256]
Definition: server.h:37
char cm_format_type
Definition: server.h:36
Definition: journaling.h:1
char * rfc822
Definition: journaling.h:9
char * subj
Definition: journaling.h:7
char * msgn
Definition: journaling.h:8
struct jnlq * next
Definition: journaling.h:2
char * rfca
Definition: journaling.h:6
struct recptypes recps
Definition: journaling.h:3
char * from
Definition: journaling.h:4
int num_internet
Definition: server.h:50
int num_room
Definition: server.h:51
char * recp_local
Definition: server.h:54
char * recp_internet
Definition: server.h:55
int num_local
Definition: server.h:49
void begin_critical_section(int which_one)
Definition: threads.c:62
void end_critical_section(int which_one)
Definition: threads.c:80