blob: 2f13f1d833e1cc560c7275b5b749962b28f01fa1 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001/*
2 * VERSION 1.0
3 * UDP MAIL system (Author: Alvin@Sushi)
4 * Requires INETD V0.60 or higher (INETD Author: Nostradamus@Zebedee)
5 */
6#pragma strict_types
7#pragma no_clone
8#pragma no_shadow
9#pragma no_inherit
10#pragma verbose_errors
11#pragma combine_strings
12//#pragma pedantic
13//#pragma range_check
14#pragma warn_deprecated
15
16#include <udp.h>
17#include <udp_mail.h>
18
19#ifdef DEBUG
20#undef DEBUG
21#endif
22#define DEBUG(x)
23
24mapping spool_item;
25
26static string *spool;
27
28private int match_mud_name(string mudname, string match_str) {
29 return mudname[0..sizeof(match_str)-1] == match_str;
30}
31
32static void save_spool_item()
33{
34 string name;
35 int count;
36
37 if(!spool_item || !mappingp(spool_item) || spool_item==([]))
38 return;
39
40 do {
41 ++count;
42 name=spool_item[UDPMS_DEST]+"-"+to_string(count);
43 } while(spool && member(spool, name)!=-1);
44
45 save_object(UDPM_SPOOL_DIR+name);
46
47 if(!spool || !sizeof(spool))
48 spool = ({ name });
49 else
50 spool += ({ name });
51}
52
53/* forward declaration */
54void deliver_mail(string recipient,string mud,string from,
55 string subj,string mail_body,int status_flag,string spool_name);
56
57/* forward declaration */
58static void start_retry_callout();
59
60static void remove_from_spool(string spool_file)
61{
Arathornb3051452021-05-13 21:13:03 +020062 if(spool && (member(spool,spool_file))!=-1)
MG Mud User88f12472016-06-24 23:31:02 +020063 {
64 spool -= ({ spool_file });
65 if(!sizeof(spool))
66 spool=0;
67 }
68
69 if(file_size("/"+UDPM_SPOOL_DIR+spool_file+".o")>0)
70 if(!rm("/"+UDPM_SPOOL_DIR+spool_file+".o"))
71 log_file(INETD_LOG_FILE,"UPD_MAIL: Can't delete spool file "+
72 "/"+UDPM_SPOOL_DIR+spool_file+".o");
73}
74
75static void retry_send()
76{
77 int i;
78 string msg;
79
80 if(!spool || !sizeof(spool)) return;
81
82 for(i=0;i<sizeof(spool);++i)
83 {
84 if(!restore_object(UDPM_SPOOL_DIR+spool[i]))
85 {
86 log_file(INETD_LOG_FILE,"UDP_MAIL: Falied to restore spool file "+
87 UDPM_SPOOL_DIR+spool[i]);
88 continue;
89 }
90
91 if(time() - spool_item[UDPMS_TIME] > UDPM_SEND_FAIL*60)
92 {
93 msg="Reason: Unable to connect to site \""+spool_item[UDPMS_DEST]+
94 "\"\n\nINCLUDED MESSAGE FOLLOWS :-\n\n"+
95 "To: "+spool_item[UDPMS_TO]+"\n"+
96 "Subject: "+spool_item[UDPMS_SUBJECT]+"\n"+
97 spool_item[UDPMS_BODY];
98
99 LOCAL_MAILER->deliver_mail(
100 spool_item[UDPMS_FROM], /* TO */
101 "Mailer@"+LOCAL_NAME, /* FROM */
102 "Bounced Mail", /* SUBJECT */
103 msg /* MAIL BODY */
104 );
105 remove_from_spool(spool[i]);
106 return;
107 }
108
109 deliver_mail(
110 spool_item[UDPMS_TO],
111 spool_item[UDPMS_DEST],
112 spool_item[UDPMS_FROM],
113 spool_item[UDPMS_SUBJECT],
114 spool_item[UDPMS_BODY],
115 UDPM_STATUS_IN_SPOOL,
116 spool[i]);
117 }
118
119 start_retry_callout();
120}
121
122static void start_retry_callout()
123{
124 if(find_call_out("retry_send")!= -1 ) return;
125
126 call_out("retry_send",UDPM_RETRY_SEND*60);
127}
128
129static void failed_to_deliver(mapping data)
130{
131 string msg;
132 object obj;
133
134 if(!data[SYSTEM] || data[SYSTEM] != TIME_OUT)
135 {
136 msg="Reason: Error in connection to remote site \""+data[NAME]+"\"\n\n"+
137 "INCLUDED MESSAGE FOLLOWS :-\n\n"+
138 "To: "+data[RECIPIENT]+"\n"+
139 "Subject: "+data[UDPM_SUBJECT]+"\n"+data[DATA];
140
141 LOCAL_MAILER->deliver_mail(
142 data[UDPM_WRITER], /* TO */
143 "Mailer@"+LOCAL_NAME, /* FROM */
144 "Bounced Mail", /* SUBJECT */
145 msg /* MAIL BODY */
146 );
147 return;
148 }
149
150 /* OK transmission timed out.. place in mail spool */
151
152 if((obj=find_player(data[UDPM_WRITER])))
153 {
154 tell_object(obj,"Mail delivery to "+data[RECIPIENT]+"@"+data[NAME]+
155 " Timed Out. Placing mail in spool.\n");
156 }
157
158 spool_item=([
159 UDPMS_TIME: time(),
160 UDPMS_TO: data[RECIPIENT],
161 UDPMS_DEST: data[NAME],
162 UDPMS_FROM: data[UDPM_WRITER],
163 UDPMS_SUBJECT: data[UDPM_SUBJECT],
164 UDPMS_BODY: data[DATA]
165 ]);
166
167 save_spool_item();
168
169 start_retry_callout();
170}
171
172static void get_pending_deliveries()
173{
174 string *entries;
175 int i;
176
177 entries=get_dir(UDPM_SPOOL_DIR+"*.o");
178 if(!entries || !sizeof(entries)) return;
179
180 spool=allocate(sizeof(entries));
181 for(i=0;i<sizeof(entries);++i)
182 spool[i]=entries[i][0..<3];
183
184 start_retry_callout();
185}
186
187void create()
188{
189 seteuid(getuid(this_object()));
190 get_pending_deliveries();
191}
192
193/*
194 * Public routines
195 */
196
197int query_valid_mail_host(string hostname)
198{
199 string *match;
200
Vanion50652322020-03-10 21:13:25 +0100201 match=filter(m_indices(({mapping})INETD->query("hosts")),
MG Mud User88f12472016-06-24 23:31:02 +0200202 #'match_mud_name,lower_case(hostname));
203
204 return (sizeof(match)==1);
205}
206
207void deliver_mail(string recipient,string mud,string from,
208 string subj,string mail_body,int status_flag,string spool_name)
209{
210 mapping data;
211
212 // Geloggt wird, wenn ein aufrufendes Objekt nicht sicher ist.
213 if (object_name(previous_object())[0..7]!="/secure/")
214 write_file("/secure/ARCH/DELIVER_MAIL",
215 sprintf("%s : Aufruf von /secure/udp_mail->deliver_mail()\n"
216 " Sender: %O Empfaenger: %O@%O\n PO: %O TI: %O TP:%O\n\n",
217 ctime(time()),from, recipient, mud,
218 previous_object(), this_interactive(), this_player()));
219
220 data=([
221 REQUEST: "mail",
222 RECIPIENT: recipient,
223 SENDER: this_object(),
224 UDPM_STATUS: status_flag,
225 UDPM_WRITER: lower_case(from),
226 UDPM_SUBJECT: subj,
227 UDPM_SPOOL_NAME: spool_name,
228 DATA: mail_body
229 ]);
230
231 INETD->_send_udp(mud,data,1);
232}
233
234void udp_reply(mapping data)
235{
236 object sender;
237
238 DEBUG(sprintf("MAILER RECEIVED %O\n",data));
239 if (!member(data,UDPM_STATUS))
240 {
241 DEBUG("BOUNCING\n");
242 LOCAL_MAILER->deliver_mail(
243 data[UDPM_WRITER], /* TO */
244 "INETD@"+data[NAME], /* FROM */
245 "Bounced Mail(No mail support yet?)", /* SUBJECT */
246 data[DATA] /* MAIL BODY */
247 );
248 if(data[UDPM_SPOOL_NAME])
249 remove_from_spool(data[UDPM_SPOOL_NAME]);
250 } else
251 switch(data[UDPM_STATUS])
252 {
253 case UDPM_STATUS_TIME_OUT:
254 failed_to_deliver(data);
255 break;
256
257 case UDPM_STATUS_DELIVERED_OK:
258 if((sender=find_player(data[UDPM_WRITER])))
259 {
260 tell_object(sender,"Mailer@"+data[NAME]+": "+
261 "Mail to "+capitalize(data[DATA])+" delivered ok.\n");
262 }
263 if(data[UDPM_SPOOL_NAME])
264 remove_from_spool(data[UDPM_SPOOL_NAME]);
265
266 break;
267
268 case UDPM_STATUS_UNKNOWN_PLAYER:
269 LOCAL_MAILER->deliver_mail(
270 data[UDPM_WRITER], /* TO */
271 "Mailer@"+data[NAME], /* FROM */
272 "Bounced Mail", /* SUBJECT */
273 data[DATA] /* MAIL BODY */
274 );
275 if(data[UDPM_SPOOL_NAME])
276 remove_from_spool(data[UDPM_SPOOL_NAME]);
277 break;
278
279 case UDPM_STATUS_IN_SPOOL:
280 /* Do nothing */
281 break;
282 }
283}