2 inherit Service.Service;
11 #define SMTP_LOG(s, args...) werror("smtp: "+s+"\n", args)
13 #define SMTP_LOG(s, args...)
16 #define MESSAGE(s, args...) werror("smtp: "+s+"\n", args)
17 #define FATAL(s, args...) werror("error: "+s+"\n", args)
19 #if constant(Protocols.SMTP.client)
20 #define SMTPCLIENT Protocols.SMTP.client
22 #define SMTPCLIENT Protocols.SMTP.Client
25 Thread.Queue MsgQueue = Thread.Queue();
26 Thread.Mutex saveMutex = Thread.Mutex();
28 object oSMTP; // cache smtp object (connection)
29 object oDNS; // cache DNS Client
32 void call_service(object user, mixed args, void|int id)
34 MsgQueue->write(args->msg);
41 dbhandle = Sql.Sql(serverCfg["database"]);
42 mixed err = catch( oDNS = Protocols.DNS.client() );
44 MESSAGE( "warning, could not create DNS client.\n" );
46 thread_create(smtp_thread);
52 private void got_kill(int sig) {
58 int main(int argc, array argv)
60 signal(signum("QUIT"), got_kill);
67 void send_message(mapping msg)
74 server = serverCfg[CFG_MAILSERVER];
75 port = (int)serverCfg[CFG_MAILPORT];
76 if ( !intp(port) || port <= 0 ) port = 25;
78 SMTP_LOG("send_message: server: %O:%O", server, port );
80 if ( !stringp(msg->from) ) {
81 msg->from = "admin@"+get_server_name();
82 SMTP_LOG("send_message: invalid 'from', using %s",
85 SMTP_LOG("send_message: mail from %O to %O (server: %O:%O)\n"+
86 " Subject: %O", msg->from, msg->email, server, port, msg->subject);
88 if ( !arrayp(msg->email) )
89 msg->email = ({ msg->email });
91 foreach ( msg->email, string email ) {
92 string tmp_server = server;
95 if ( stringp(server) && sizeof(server) > 0 ) {
97 smtp = SMTPCLIENT( server, port );
101 // if no server is configured use the e-mail of the receiver
103 sscanf( email, "%*s@%s", host );
104 if ( !stringp(host) )
105 error("MX Lookup failed, host = 0 in %O", msg->email);
107 if ( !objectp(oDNS) )
108 error("MX Lookup failed, no DNS");
109 tmp_server = oDNS->get_primary_mx(host);
110 array dns_data = oDNS->gethostbyname(tmp_server);
111 if ( arrayp(dns_data) && sizeof(dns_data) > 1 &&
112 arrayp(dns_data[1]) && sizeof(dns_data[1]) > 0 )
113 tmp_server = dns_data[1][0];
115 SMTP_LOG("send_message: MX lookup: %O:%O",
116 tmp_server, tmp_port );
118 smtp = SMTPCLIENT( tmp_server, tmp_port );
122 if ( !objectp(smtp) || smtp_error ) {
123 string msg = sprintf( "Invalid mail server %O:%O (from %O to %O)\n",
124 tmp_server, tmp_port, msg->from, email );
125 if ( smtp_error ) msg += sprintf( "%O", smtp_error );
130 if ( stringp(msg->rawmime) ) {
133 smtp->send_message(msg->from, ({ email }), msg->rawmime);
136 FATAL("Failed to send mail directly from %O to %O via %O:%O : %O",
137 msg->from, email, tmp_server, tmp_port, smtp_error[0]);
140 MESSAGE("Mail sent directly from %O to %O via %O:%O\n",
141 msg->from, email, tmp_server, tmp_port );
146 if ( !stringp(msg->mimetype) )
147 msg->mimetype = "text/plain";
152 ([ "Content-Type": (msg->mimetype||"text/plain") + "; charset=utf-8",
153 "Mime-Version": "1.0 (generated by open-sTeam)",
154 "Subject": msg->subject||"",
155 "Date": msg->date || timelib.smtp_time(time()),
156 "From": msg->fromname||msg->from||msg->fromobj||"",
157 "To": (msg->fromobj ? msg->fromobj : email)||"",
158 "Message-Id": msg->message_id||"",
161 if(msg->mail_followup_to)
162 mmsg->headers["Mail-Followup-To"]=msg->mail_followup_to;
164 mmsg->headers["Reply-To"]=msg->reply_to;
166 mmsg->headers["In-Reply-To"]=msg->in_reply_to;
169 smtp->send_message(msg->from, ({ email }), (string)mmsg);
172 FATAL("Failed to send mail from %O to %O via %O:%O"
173 + " : %O\n", msg->from, email, tmp_server, tmp_port, smtp_error[0] );
176 MESSAGE("Mail sent from %O to %O via %O:%O\n",
177 msg->from, email, tmp_server, tmp_port );
182 void delete_mail(mapping msg)
184 dbhandle->big_query(sprintf("delete from i_rawmails where mailid='%d'",
194 SMTP_LOG("smtp-thread running...");
195 msg = MsgQueue->read();
199 MESSAGE("Message from %O to %O sent: '%O'",
200 msg->from, msg->email,
201 (stringp(msg->rawmime)?"mime message": msg->subject));
204 FATAL("Error while sending message:" + err[0] +
205 sprintf("\n%O\n", err[1]));
206 FATAL("MAILSERVER="+serverCfg[CFG_MAILSERVER]);
207 if ( objectp(oSMTP) ) {
211 sleep(60); // wait one minute before retrying