blob: 3203fb95f0d42a4580a4a7f766e6de331cb3c0cd [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{
62 int idx;
63
64 if(spool && (idx=member(spool,spool_file))!=-1)
65 {
66 spool -= ({ spool_file });
67 if(!sizeof(spool))
68 spool=0;
69 }
70
71 if(file_size("/"+UDPM_SPOOL_DIR+spool_file+".o")>0)
72 if(!rm("/"+UDPM_SPOOL_DIR+spool_file+".o"))
73 log_file(INETD_LOG_FILE,"UPD_MAIL: Can't delete spool file "+
74 "/"+UDPM_SPOOL_DIR+spool_file+".o");
75}
76
77static void retry_send()
78{
79 int i;
80 string msg;
81
82 if(!spool || !sizeof(spool)) return;
83
84 for(i=0;i<sizeof(spool);++i)
85 {
86 if(!restore_object(UDPM_SPOOL_DIR+spool[i]))
87 {
88 log_file(INETD_LOG_FILE,"UDP_MAIL: Falied to restore spool file "+
89 UDPM_SPOOL_DIR+spool[i]);
90 continue;
91 }
92
93 if(time() - spool_item[UDPMS_TIME] > UDPM_SEND_FAIL*60)
94 {
95 msg="Reason: Unable to connect to site \""+spool_item[UDPMS_DEST]+
96 "\"\n\nINCLUDED MESSAGE FOLLOWS :-\n\n"+
97 "To: "+spool_item[UDPMS_TO]+"\n"+
98 "Subject: "+spool_item[UDPMS_SUBJECT]+"\n"+
99 spool_item[UDPMS_BODY];
100
101 LOCAL_MAILER->deliver_mail(
102 spool_item[UDPMS_FROM], /* TO */
103 "Mailer@"+LOCAL_NAME, /* FROM */
104 "Bounced Mail", /* SUBJECT */
105 msg /* MAIL BODY */
106 );
107 remove_from_spool(spool[i]);
108 return;
109 }
110
111 deliver_mail(
112 spool_item[UDPMS_TO],
113 spool_item[UDPMS_DEST],
114 spool_item[UDPMS_FROM],
115 spool_item[UDPMS_SUBJECT],
116 spool_item[UDPMS_BODY],
117 UDPM_STATUS_IN_SPOOL,
118 spool[i]);
119 }
120
121 start_retry_callout();
122}
123
124static void start_retry_callout()
125{
126 if(find_call_out("retry_send")!= -1 ) return;
127
128 call_out("retry_send",UDPM_RETRY_SEND*60);
129}
130
131static void failed_to_deliver(mapping data)
132{
133 string msg;
134 object obj;
135
136 if(!data[SYSTEM] || data[SYSTEM] != TIME_OUT)
137 {
138 msg="Reason: Error in connection to remote site \""+data[NAME]+"\"\n\n"+
139 "INCLUDED MESSAGE FOLLOWS :-\n\n"+
140 "To: "+data[RECIPIENT]+"\n"+
141 "Subject: "+data[UDPM_SUBJECT]+"\n"+data[DATA];
142
143 LOCAL_MAILER->deliver_mail(
144 data[UDPM_WRITER], /* TO */
145 "Mailer@"+LOCAL_NAME, /* FROM */
146 "Bounced Mail", /* SUBJECT */
147 msg /* MAIL BODY */
148 );
149 return;
150 }
151
152 /* OK transmission timed out.. place in mail spool */
153
154 if((obj=find_player(data[UDPM_WRITER])))
155 {
156 tell_object(obj,"Mail delivery to "+data[RECIPIENT]+"@"+data[NAME]+
157 " Timed Out. Placing mail in spool.\n");
158 }
159
160 spool_item=([
161 UDPMS_TIME: time(),
162 UDPMS_TO: data[RECIPIENT],
163 UDPMS_DEST: data[NAME],
164 UDPMS_FROM: data[UDPM_WRITER],
165 UDPMS_SUBJECT: data[UDPM_SUBJECT],
166 UDPMS_BODY: data[DATA]
167 ]);
168
169 save_spool_item();
170
171 start_retry_callout();
172}
173
174static void get_pending_deliveries()
175{
176 string *entries;
177 int i;
178
179 entries=get_dir(UDPM_SPOOL_DIR+"*.o");
180 if(!entries || !sizeof(entries)) return;
181
182 spool=allocate(sizeof(entries));
183 for(i=0;i<sizeof(entries);++i)
184 spool[i]=entries[i][0..<3];
185
186 start_retry_callout();
187}
188
189void create()
190{
191 seteuid(getuid(this_object()));
192 get_pending_deliveries();
193}
194
195/*
196 * Public routines
197 */
198
199int query_valid_mail_host(string hostname)
200{
201 string *match;
202
203 match=filter(m_indices((mapping)INETD->query("hosts")),
204 #'match_mud_name,lower_case(hostname));
205
206 return (sizeof(match)==1);
207}
208
209void deliver_mail(string recipient,string mud,string from,
210 string subj,string mail_body,int status_flag,string spool_name)
211{
212 mapping data;
213
214 // Geloggt wird, wenn ein aufrufendes Objekt nicht sicher ist.
215 if (object_name(previous_object())[0..7]!="/secure/")
216 write_file("/secure/ARCH/DELIVER_MAIL",
217 sprintf("%s : Aufruf von /secure/udp_mail->deliver_mail()\n"
218 " Sender: %O Empfaenger: %O@%O\n PO: %O TI: %O TP:%O\n\n",
219 ctime(time()),from, recipient, mud,
220 previous_object(), this_interactive(), this_player()));
221
222 data=([
223 REQUEST: "mail",
224 RECIPIENT: recipient,
225 SENDER: this_object(),
226 UDPM_STATUS: status_flag,
227 UDPM_WRITER: lower_case(from),
228 UDPM_SUBJECT: subj,
229 UDPM_SPOOL_NAME: spool_name,
230 DATA: mail_body
231 ]);
232
233 INETD->_send_udp(mud,data,1);
234}
235
236void udp_reply(mapping data)
237{
238 object sender;
239
240 DEBUG(sprintf("MAILER RECEIVED %O\n",data));
241 if (!member(data,UDPM_STATUS))
242 {
243 DEBUG("BOUNCING\n");
244 LOCAL_MAILER->deliver_mail(
245 data[UDPM_WRITER], /* TO */
246 "INETD@"+data[NAME], /* FROM */
247 "Bounced Mail(No mail support yet?)", /* SUBJECT */
248 data[DATA] /* MAIL BODY */
249 );
250 if(data[UDPM_SPOOL_NAME])
251 remove_from_spool(data[UDPM_SPOOL_NAME]);
252 } else
253 switch(data[UDPM_STATUS])
254 {
255 case UDPM_STATUS_TIME_OUT:
256 failed_to_deliver(data);
257 break;
258
259 case UDPM_STATUS_DELIVERED_OK:
260 if((sender=find_player(data[UDPM_WRITER])))
261 {
262 tell_object(sender,"Mailer@"+data[NAME]+": "+
263 "Mail to "+capitalize(data[DATA])+" delivered ok.\n");
264 }
265 if(data[UDPM_SPOOL_NAME])
266 remove_from_spool(data[UDPM_SPOOL_NAME]);
267
268 break;
269
270 case UDPM_STATUS_UNKNOWN_PLAYER:
271 LOCAL_MAILER->deliver_mail(
272 data[UDPM_WRITER], /* TO */
273 "Mailer@"+data[NAME], /* FROM */
274 "Bounced Mail", /* SUBJECT */
275 data[DATA] /* MAIL BODY */
276 );
277 if(data[UDPM_SPOOL_NAME])
278 remove_from_spool(data[UDPM_SPOOL_NAME]);
279 break;
280
281 case UDPM_STATUS_IN_SPOOL:
282 /* Do nothing */
283 break;
284 }
285}