diff options
author | pixel <pixel> | 2007-10-12 13:07:42 +0000 |
---|---|---|
committer | pixel <pixel> | 2007-10-12 13:07:42 +0000 |
commit | f17840bffba5b1e5eb7d0ab3712513e81deebfaa (patch) | |
tree | a366c772fd19dd740cd5e13d8bfda9f28dfc3677 /lib | |
parent | 54885ea33f4022e552784e63df1c75fc26e181dd (diff) |
Adding SocketClient and MailClient.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/MailClient.cc | 263 | ||||
-rw-r--r-- | lib/SocketClient.cc | 88 |
2 files changed, 351 insertions, 0 deletions
diff --git a/lib/MailClient.cc b/lib/MailClient.cc new file mode 100644 index 0000000..380c878 --- /dev/null +++ b/lib/MailClient.cc @@ -0,0 +1,263 @@ +/* + * Baltisot + * Copyright (C) 1999-2007 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 + */ + +/* $Id: MailClient.cc,v 1.1 2007-10-12 13:07:42 pixel Exp $ */ + +#include <TaskMan.h> +#include <MailClient.h> +#include <BRegex.h> +#include <CopyJob.h> +#include <ReadJob.h> +#include <Variables.h> + +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<String>::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 *(ptr++); +} + +int MailClient::Do() throw (GeneralException) { + int code; + std::vector<String>::iterator i; + String n; + + subDo(); + switch (current) { + case 0: + WaitFor(c = new ReadJob(&s, &b, final_line)); + 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)); + current = 2; + Suspend(TASK_ON_HOLD); + + case 2: + WaitFor(c = new ReadJob(&s, &b, final_line)); + 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)); + current = 4; + Suspend(TASK_ON_HOLD); + + case 4: + WaitFor(c = new ReadJob(&s, &b, final_line)); + 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 rejecter one RCPT TO, nevermind it. + } + } + + n = getNext(); + + if (cur_rcpt != RCPT_END) { + b << "RCPT TO: " << n << "\r\n"; + WaitFor(c = new CopyJob(&b, &s)); + current = 4; + Suspend(TASK_ON_HOLD); + } + + b << "DATA\r\n"; + WaitFor(c = new CopyJob(&b, &s)); + current = 6; + Suspend(TASK_ON_HOLD); + + case 6: + WaitFor(c = new ReadJob(&s, &b, final_line)); + 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)); + current = 8; + Suspend(TASK_ON_HOLD); + + case 8: + WaitFor(c = new ReadJob(&s, &b, final_line)); + current = 9; + Suspend(TASK_ON_HOLD); + + case 9: + if (readCode() != 250) { + status = "SMTP rejected our mail: " + msg; + return TASK_DONE; + } + + b << "QUIT\n\r"; + WaitFor(c = new CopyJob(&b, &s)); + current = 10; + Suspend(TASK_ON_HOLD); + + case 10: + WaitFor(c = new ReadJob(&s, &b, final_line)); + 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; + } +} diff --git a/lib/SocketClient.cc b/lib/SocketClient.cc new file mode 100644 index 0000000..a86629a --- /dev/null +++ b/lib/SocketClient.cc @@ -0,0 +1,88 @@ +/* + * Baltisot + * Copyright (C) 1999-2007 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 + */ + +/* $Id: SocketClient.cc,v 1.1 2007-10-12 13:07:42 pixel Exp $ */ + +#include <TaskMan.h> +#include <SocketClient.h> +#include <BRegex.h> +#include <CopyJob.h> +#include <ReadJob.h> +#include <Variables.h> + +timeval default_socket_timeout = { 8, 0 }; + +SocketClient::SocketClient(const String & host, int port, timeval _timeout) : timeout(_timeout) { + s.SetNonBlock(); + s.Connect(host, 25); + + if (s.IsConnected()) { + SetBurst(); + } else { + WaitFor(timeout); + WaitFor(&s, W4_WRITING); + } +} + +SocketClient::~SocketClient() { +} + +String SocketClient::GetStatus() { + return status; +} + +void SocketClient::SetStatus(const String & _status) { + status = _status; +} + +void SocketClient::subDo() throw (GeneralException) { + switch (current) { + case 0: + if (s.IsConnecting() && (TaskMan::Event() == Task::EVT_HANDLE)) { + s.FinalizeConnect(); + } + if (TaskMan::Event() == Task::EVT_TIMEOUT) { + status = "Connection timeout"; + Suspend(TASK_DONE); + } + if (!s.IsConnected()) { + status = "Connection failed"; + Suspend(TASK_DONE); + } + RemoveTimeout(); + + WaitFor(timeout); + return; + + default: + if (c) + delete c; + + c = 0; + + if (TaskMan::Event() == Task::Task::EVT_TIMEOUT) { + status = "Connection timeout."; + Suspend(TASK_DONE); + } + RemoveTimeout(); + + WaitFor(timeout); + return; + } +} |