/* * Baltisot * Copyright (C) 1999-2008 Nicolas "Pixel" Noble * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include const timeval timeout = { 8, 0 }; MailClient::MailClient(const String & _smtp, const String & _subject, const String & _from, strings_t _headers, strings_t _tos, strings_t _ccs, strings_t _bccs, strings_t _fakes, Handle * _body) : SocketClient(_smtp, 25), smtp(_smtp), subject(_subject), from(_from), headers(_headers), tos(_tos), ccs(_ccs), bccs(_bccs), fakes(_fakes), body(_body), cur_rcpt(RCPT_BEGIN) { SetStatus("Starting"); } MailClient::~MailClient() { } static Regex final_line("^[0-9]{3} "); int MailClient::readCode() { do { b >> msg; } while (!final_line.Match(msg)); return msg.to_int(); } String MailClient::getEmail(const String & recipient) { int pos_1, pos_2; if ((pos_1 = recipient.strchr('<')) == -1) return recipient; if ((pos_2 = recipient.strrchr('>')) == -1) return recipient; return recipient.extract(pos_1 + 1, pos_2 - 1); } void MailClient::writeEmail(Handle * out) { String l; std::vector::iterator i; (*out) << "Subject: " << subject << "\r\n"; (*out) << "From: " << from << "\r\n"; for (i = headers.begin(); i != headers.end(); i++) { (*out) << *i << "\r\n"; } if (!fakes.empty()) { (*out) << "To: "; for (i = fakes.begin(); i != fakes.end(); i++) { if (i != fakes.begin()) (*out) << ";"; (*out) << *i; } (*out) << "\r\n"; } else { if (!tos.empty()) { (*out) << "To: "; for (i = tos.begin(); i != tos.end(); i++) { if (i != tos.begin()) (*out) << ";"; (*out) << *i; } (*out) << "\r\n"; } if (!ccs.empty()) { (*out) << "To: "; for (i = ccs.begin(); i != ccs.end(); i++) { if (i != ccs.begin()) (*out) << ";"; (*out) << *i; } (*out) << "\r\n"; } if (!bccs.empty()) { (*out) << "To: "; for (i = bccs.begin(); i != bccs.end(); i++) { if (i != bccs.begin()) (*out) << ";"; (*out) << *i; } (*out) << "\r\n"; } } (*out) << "\r\n"; while (!body->IsClosed()) { (*body) >> l; if (l[0] == '.') (*out) << "."; (*out) << l << "\r\n"; } (*out) << ".\r\n"; } String MailClient::getNext() { if (cur_rcpt == RCPT_BEGIN) { ptr = tos.begin(); end = tos.end(); cur_rcpt = RCPT_TOS; } while (ptr == end) { switch (cur_rcpt) { case RCPT_TOS: cur_rcpt = RCPT_CCS; ptr = ccs.begin(); end = ccs.end(); break; case RCPT_CCS: cur_rcpt = RCPT_BCCS; ptr = bccs.begin(); end = bccs.end(); break; case RCPT_BCCS: cur_rcpt = RCPT_END; return "**END**"; } } return getEmail(*(ptr++)); } int MailClient::Do() throw (GeneralException) { std::vector::iterator i; String n; subDo(); switch (current) { case 0: WaitFor(c = new ReadJob(&s, &b, final_line)); WaitTimeout(); current = 1; Suspend(TASK_ON_HOLD); case 1: if (readCode() != 220) { status = "Can not establish connection: " + msg; return TASK_DONE; } b << "EHLO foobar\r\n"; WaitFor(c = new CopyJob(&b, &s)); WaitTimeout(); current = 2; Suspend(TASK_ON_HOLD); case 2: WaitFor(c = new ReadJob(&s, &b, final_line)); WaitTimeout(); current = 3; Suspend(TASK_ON_HOLD); case 3: if (readCode() != 250) { status = "SMTP server rejected our EHLO: " + msg; return TASK_DONE; } b << "MAIL FROM: " << getEmail(from) << "\r\n"; WaitFor(c = new CopyJob(&b, &s)); WaitTimeout(); current = 4; Suspend(TASK_ON_HOLD); case 4: WaitFor(c = new ReadJob(&s, &b, final_line)); WaitTimeout(); current = 5; Suspend(TASK_ON_HOLD); case 5: if (readCode() != 250) { if (cur_rcpt == RCPT_BEGIN) { status = "SMTP server rejected our MAIL FROM: " + msg; return TASK_DONE; // } else { // SMTP server rejected one RCPT TO, nevermind it. } } n = getNext(); if (cur_rcpt != RCPT_END) { b << "RCPT TO: " << n << "\r\n"; WaitFor(c = new CopyJob(&b, &s)); WaitTimeout(); current = 4; Suspend(TASK_ON_HOLD); } b << "DATA\r\n"; WaitFor(c = new CopyJob(&b, &s)); WaitTimeout(); current = 6; Suspend(TASK_ON_HOLD); case 6: WaitFor(c = new ReadJob(&s, &b, final_line)); WaitTimeout(); current = 7; Suspend(TASK_ON_HOLD); case 7: if (readCode() != 354) { status = "SMTP rejected our DATA command: " + msg; return TASK_DONE; } writeEmail(&b); WaitFor(c = new CopyJob(&b, &s)); WaitTimeout(); current = 8; Suspend(TASK_ON_HOLD); case 8: WaitFor(c = new ReadJob(&s, &b, final_line)); WaitTimeout(); current = 9; Suspend(TASK_ON_HOLD); case 9: if (readCode() != 250) { status = "SMTP rejected our mail: " + msg; return TASK_DONE; } b << "QUIT\r\n"; WaitFor(c = new CopyJob(&b, &s)); WaitTimeout(); current = 10; Suspend(TASK_ON_HOLD); case 10: WaitFor(c = new ReadJob(&s, &b, final_line)); WaitTimeout(); current = 11; Suspend(TASK_ON_HOLD); case 11: if (readCode() != 221) status = "SMTP wasn't pleased by our QUIT command: " + msg; status = "Mail sent."; return TASK_DONE; } }