Darryl Pogue
13 years ago
5 changed files with 0 additions and 915 deletions
@ -1,16 +0,0 @@
|
||||
include_directories("../../CoreLib") |
||||
include_directories("../../NucleusLib") |
||||
|
||||
set(pnMail_HEADERS |
||||
Pch.h |
||||
pnMail.h |
||||
) |
||||
|
||||
set(pnMail_SOURCES |
||||
pnMail.cpp |
||||
) |
||||
|
||||
add_library(pnMail STATIC ${pnMail_HEADERS} ${pnMail_SOURCES}) |
||||
|
||||
source_group("Header Files" FILES ${pnMail_HEADERS}) |
||||
source_group("Source Files" FILES ${pnMail_SOURCES}) |
@ -1,60 +0,0 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools |
||||
Copyright (C) 2011 Cyan Worlds, Inc. |
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7 |
||||
|
||||
If you modify this Program, or any covered work, by linking or |
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
||||
(or a modified version of those libraries), |
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
||||
licensors of this Program grant you additional |
||||
permission to convey the resulting work. Corresponding Source for a |
||||
non-source form of such a combination shall include the source code for |
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
||||
work. |
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
||||
or by snail mail at: |
||||
Cyan Worlds, Inc. |
||||
14617 N Newport Hwy |
||||
Mead, WA 99021 |
||||
|
||||
*==LICENSE==*/ |
||||
/*****************************************************************************
|
||||
* |
||||
* $/Plasma20/Sources/Plasma/NucleusLib/pnMail/Pch.h |
||||
*
|
||||
***/ |
||||
|
||||
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNMAIL_PCH_H |
||||
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnMail/Pch.h included more than once" |
||||
#endif |
||||
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNMAIL_PCH_H |
||||
|
||||
|
||||
#include "pnUtils/pnUtils.h" |
||||
#include "pnNetBase/pnNetBase.h" |
||||
#include "pnAsyncCore/pnAsyncCore.h" |
||||
|
||||
#include "pnMail.h" |
||||
|
||||
#include <malloc.h> |
@ -1,726 +0,0 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools |
||||
Copyright (C) 2011 Cyan Worlds, Inc. |
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7 |
||||
|
||||
If you modify this Program, or any covered work, by linking or |
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
||||
(or a modified version of those libraries), |
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
||||
licensors of this Program grant you additional |
||||
permission to convey the resulting work. Corresponding Source for a |
||||
non-source form of such a combination shall include the source code for |
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
||||
work. |
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
||||
or by snail mail at: |
||||
Cyan Worlds, Inc. |
||||
14617 N Newport Hwy |
||||
Mead, WA 99021 |
||||
|
||||
*==LICENSE==*/ |
||||
/*****************************************************************************
|
||||
* |
||||
* $/Plasma20/Sources/Plasma/NucleusLib/pnMail/pnMail.cpp |
||||
*
|
||||
***/ |
||||
|
||||
#include "Pch.h" |
||||
#pragma hdrstop |
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* |
||||
* Private |
||||
* |
||||
***/ |
||||
|
||||
enum EMailStep { |
||||
kMailStepConnect, // wait for 220, then send "helo" command
|
||||
kMailStepAuth, // wait for 250, then send "AUTH PLAIN <base64data>"
|
||||
kMailStepSender, // wait for 235/250, then send "mail from:" command
|
||||
kMailStepRecipient, // wait for 250, then send "rcpt to:" command
|
||||
kMailStepStartLetter, // wait for 250, then send "data" command
|
||||
kMailStepLetter, // wait for 354, then send letter
|
||||
kMailStepQuit, // wait for 250, then send "quit" command
|
||||
kMailStepDisconnect, // wait for 221, then disconnect
|
||||
}; |
||||
|
||||
|
||||
struct MailTransaction { |
||||
LINK(MailTransaction) link; |
||||
AsyncSocket sock; |
||||
const char ** stepTable; |
||||
EMailStep step; |
||||
unsigned subStep; |
||||
EMailError error; |
||||
FMailResult callback; |
||||
void * param; |
||||
|
||||
char * smtp; |
||||
char * sender; |
||||
char * recipient; |
||||
char * replyTo; |
||||
char * subject; |
||||
char * bodyEncoding; |
||||
char * body; |
||||
char * auth; |
||||
char buffer[1]; |
||||
}; |
||||
|
||||
static bool MailNotifyProc ( |
||||
AsyncSocket sock, |
||||
EAsyncNotifySocket code, |
||||
AsyncNotifySocket * notify, |
||||
void ** userState |
||||
); |
||||
|
||||
static void CDECL Send ( |
||||
AsyncSocket sock, |
||||
const char str[], |
||||
... |
||||
); |
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* |
||||
* Private data |
||||
* |
||||
***/ |
||||
|
||||
static bool s_shutdown; |
||||
static CCritSect s_critsect; |
||||
static LISTDECL(MailTransaction, link) s_mail; |
||||
|
||||
|
||||
//===========================================================================
|
||||
// Authenticated email sequence
|
||||
// -> "220 catherine.cyan.com ESMTP\r\n"
|
||||
// <- "HELO cyan.com\r\n"
|
||||
// -> "250 catherine.cyan.com\r\n"
|
||||
// <- "AUTH PLAIN XXXXXXXXX\r\n"
|
||||
// -> "235 go ahead\r\n"
|
||||
// <- "MAIL FROM:<UruClient@cyanworlds.com>\r\n"
|
||||
// -> "250 ok mail from accepted\r\n"
|
||||
// <- "RCPT TO:<UruCrashReport@cyanworlds.com>\r\n"
|
||||
// -> "250 ok recipient accepted\r\n"
|
||||
// <- "DATA\r\n"
|
||||
// -> "354 ok, go ahead:\r\n"
|
||||
// -> <message> + "\r\n.\r\n"
|
||||
// -> "250 message accepted for delivery\r\n"
|
||||
// <- "QUIT\r\n"
|
||||
// -> "221 catherine.cyan.com\r\n"
|
||||
//===========================================================================
|
||||
static const char * s_waitStrAuth[] = { |
||||
"220 ", // kMailStepConnect
|
||||
"250 ", // kMailStepAuth
|
||||
"235 ", // kMailStepSender
|
||||
"250 ", // kMailStepRecipient
|
||||
"250 ", // kMailStepStartLetter
|
||||
"354 ", // kMailStepLetter
|
||||
"250 ", // kMailStepQuit
|
||||
"221 ", // kMailStepDisconnect
|
||||
}; |
||||
|
||||
//===========================================================================
|
||||
// Unauthenticated email seqeunce
|
||||
// -> "220 catherine.cyan.com ESMTP\r\n"
|
||||
// <- "HELO cyan.com\r\n"
|
||||
// -> "250 catherine.cyan.com\r\n"
|
||||
// <- "MAIL FROM:<UruClient@cyanworlds.com>\r\n"
|
||||
// -> "250 ok mail from accepted\r\n"
|
||||
// <- "RCPT TO:<UruCrashReport@cyanworlds.com>\r\n"
|
||||
// -> "250 ok recipient accepted\r\n"
|
||||
// <- "DATA\r\n"
|
||||
// -> "354 ok, go ahead:\r\n"
|
||||
// -> <message> + "\r\n.\r\n"
|
||||
// -> "250 message accepted for delivery\r\n"
|
||||
// <- "QUIT\r\n"
|
||||
// -> "221 catherine.cyan.com\r\n"
|
||||
//===========================================================================
|
||||
static const char * s_waitStrNoAuth[] = { |
||||
"220 ", // kMailStepConnect
|
||||
nil, // kMailStepAuth
|
||||
"250 ", // kMailStepSender
|
||||
"250 ", // kMailStepRecipient
|
||||
"250 ", // kMailStepStartLetter
|
||||
"354 ", // kMailStepLetter
|
||||
"250 ", // kMailStepQuit
|
||||
"221 ", // kMailStepDisconnect
|
||||
}; |
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* |
||||
* Internal functions |
||||
* |
||||
***/ |
||||
|
||||
//===========================================================================
|
||||
static bool AdvanceStep ( |
||||
MailTransaction * transaction, |
||||
AsyncSocket sock |
||||
) { |
||||
switch (transaction->step) { |
||||
case kMailStepConnect: { |
||||
const char * host = transaction->sender; |
||||
const char * separator = StrChr(host, '@'); |
||||
if (separator) |
||||
host = separator + 1; |
||||
Send(sock, "helo ", host, "\r\n", nil); |
||||
transaction->step = kMailStepSender; |
||||
|
||||
if (transaction->auth[0]) |
||||
transaction->step = kMailStepAuth; |
||||
} |
||||
break; |
||||
|
||||
case kMailStepAuth: |
||||
Send(sock, "AUTH PLAIN ", transaction->auth, "\r\n", nil); |
||||
transaction->step = kMailStepSender; |
||||
break; |
||||
|
||||
case kMailStepSender: |
||||
Send(sock, "mail from:<", transaction->sender, ">\r\n", nil); |
||||
transaction->step = kMailStepRecipient; |
||||
break; |
||||
|
||||
case kMailStepRecipient: { |
||||
const char * start = transaction->recipient + transaction->subStep; |
||||
while (*start == ' ') |
||||
++start; |
||||
const char * term = StrChr(start, ';'); |
||||
if (term) { |
||||
char * buffer = (char*)malloc(term + 1 - start); |
||||
StrCopy(buffer, start, term + 1 - start); |
||||
Send(sock, "rcpt to:<", buffer, ">\r\n", nil); |
||||
transaction->subStep = term + 1 - transaction->recipient; |
||||
|
||||
free(buffer); |
||||
} |
||||
else { |
||||
Send(sock, "rcpt to:<", start, ">\r\n", nil); |
||||
transaction->step = kMailStepStartLetter; |
||||
transaction->subStep = 0; |
||||
} |
||||
} |
||||
break; |
||||
|
||||
case kMailStepStartLetter: |
||||
Send(sock, "data\r\n", nil); |
||||
transaction->step = kMailStepLetter; |
||||
break; |
||||
|
||||
case kMailStepLetter: |
||||
if (transaction->replyTo[0]) { |
||||
Send( |
||||
sock, |
||||
"Reply-to: ", |
||||
transaction->replyTo, |
||||
"\r\n", |
||||
nil |
||||
); |
||||
} |
||||
if (transaction->bodyEncoding) { |
||||
Send( |
||||
sock,
|
||||
"From: ", |
||||
transaction->sender, |
||||
"\r\nTo: ", |
||||
transaction->recipient, |
||||
"\r\nSubject: ", |
||||
transaction->subject, |
||||
"\r\nContent-Type: text/plain; charset=", |
||||
transaction->bodyEncoding, |
||||
"\r\n\r\n", |
||||
transaction->body, |
||||
"\r\n.\r\n", |
||||
nil |
||||
); |
||||
} |
||||
else { |
||||
Send( |
||||
sock,
|
||||
"From: ", |
||||
transaction->sender, |
||||
"\r\nTo: ", |
||||
transaction->recipient, |
||||
"\r\nSubject: ", |
||||
transaction->subject, |
||||
"\r\n\r\n", |
||||
transaction->body, |
||||
"\r\n.\r\n", |
||||
nil |
||||
); |
||||
} |
||||
transaction->step = kMailStepQuit; |
||||
break; |
||||
|
||||
case kMailStepQuit: |
||||
Send(sock, "quit\r\n", nil); |
||||
transaction->step = kMailStepDisconnect; |
||||
break; |
||||
|
||||
case kMailStepDisconnect: |
||||
return false; |
||||
|
||||
DEFAULT_FATAL(transaction->step); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
//===========================================================================
|
||||
static bool NotifyRead ( |
||||
AsyncSocket sock, |
||||
AsyncNotifySocketRead * read, |
||||
MailTransaction * transaction |
||||
) { |
||||
|
||||
// Parse available lines looking for an acknowledgement of last command
|
||||
const char * compareStr = transaction->stepTable[transaction->step]; |
||||
unsigned compareLen = StrLen(compareStr); |
||||
unsigned offset = 0; |
||||
for (;;) { |
||||
const char * source = (const char *)&read->buffer[offset]; |
||||
|
||||
// Search for an end-of-line marker
|
||||
const char * eol = StrChr(source, '\n', read->bytes - offset); |
||||
if (!eol) |
||||
break; |
||||
offset += (eol + 1 - source); |
||||
|
||||
// Search for an acknowledgement
|
||||
if (!StrCmp(source, compareStr, compareLen)) { |
||||
read->bytesProcessed = offset; |
||||
return AdvanceStep(transaction, sock); |
||||
} |
||||
|
||||
// An error was received; log it and bail
|
||||
LogMsg( |
||||
kLogError, |
||||
"Mail: step %u error '%.*s'", |
||||
transaction->step, |
||||
eol - source - 1, |
||||
source |
||||
); |
||||
transaction->error = kMailErrServerError; |
||||
return false; |
||||
} |
||||
|
||||
// We did not find an acknowledgement, so skip past fully-received lines
|
||||
// and wait for more data to arrive
|
||||
read->bytesProcessed = offset; |
||||
return true; |
||||
|
||||
} |
||||
|
||||
//===========================================================================
|
||||
static void DestroyTransaction (MailTransaction * transaction) { |
||||
|
||||
// Remove transaction from list so that it can
|
||||
// be safely deleted outside the critical section
|
||||
s_critsect.Enter(); |
||||
{ |
||||
s_mail.Unlink(transaction); |
||||
} |
||||
s_critsect.Leave(); |
||||
|
||||
// Perform callback if requested
|
||||
if (transaction->callback) { |
||||
transaction->callback( |
||||
transaction->param, |
||||
transaction->error |
||||
); |
||||
} |
||||
|
||||
delete transaction; |
||||
} |
||||
|
||||
//===========================================================================
|
||||
static void MailLookupProc ( |
||||
void * param, |
||||
const wchar_t * , |
||||
unsigned addrCount, |
||||
const NetAddress addrs[] |
||||
) { |
||||
|
||||
// If no address was found, cancel the transaction
|
||||
MailTransaction * transaction = (MailTransaction *) param; |
||||
if (!addrCount) { |
||||
LogMsg(kLogError,"Mail: failed to resolve %s", transaction->smtp); |
||||
transaction->error = kMailErrDnsFailed; |
||||
DestroyTransaction(transaction); |
||||
return; |
||||
} |
||||
|
||||
// Initiate a connection
|
||||
AsyncCancelId cancelId; |
||||
AsyncSocketConnect( |
||||
&cancelId, |
||||
addrs[0], |
||||
MailNotifyProc, |
||||
transaction |
||||
); |
||||
|
||||
} |
||||
|
||||
//===========================================================================
|
||||
static bool MailNotifyProc ( |
||||
AsyncSocket sock, |
||||
EAsyncNotifySocket code, |
||||
AsyncNotifySocket * notify, |
||||
void ** userState |
||||
) { |
||||
switch (code) { |
||||
case kNotifySocketConnectFailed: { |
||||
MailTransaction * transaction = (MailTransaction *)notify->param; |
||||
LogMsg(kLogError, "Mail: unable to connect to %s", transaction->smtp); |
||||
transaction->error = kMailErrConnectFailed; |
||||
DestroyTransaction(transaction); |
||||
} |
||||
break; |
||||
|
||||
case kNotifySocketConnectSuccess: { |
||||
MailTransaction * transaction = (MailTransaction *) notify->param; |
||||
*userState = notify->param; |
||||
transaction->sock = sock; |
||||
} |
||||
break; |
||||
|
||||
case kNotifySocketRead: { |
||||
MailTransaction * transaction = (MailTransaction *) *userState; |
||||
return NotifyRead(sock, (AsyncNotifySocketRead *) notify, transaction); |
||||
} |
||||
break; |
||||
|
||||
case kNotifySocketDisconnect: { |
||||
MailTransaction * transaction = (MailTransaction *) *userState; |
||||
if ((transaction->step != kMailStepDisconnect) && !transaction->error) { |
||||
transaction->error = kMailErrDisconnected; |
||||
LogMsg(kLogError, "Mail: unexpected disconnection from %s", transaction->smtp); |
||||
} |
||||
DestroyTransaction(transaction); |
||||
AsyncSocketDelete(sock); |
||||
} |
||||
break; |
||||
} |
||||
|
||||
return !s_shutdown; |
||||
} |
||||
|
||||
//===========================================================================
|
||||
static void CDECL Send ( |
||||
AsyncSocket sock, |
||||
const char str[], |
||||
... |
||||
) { |
||||
// Count bytes
|
||||
unsigned bytes = 1; |
||||
{ |
||||
va_list argList; |
||||
va_start(argList, str); |
||||
for (const char * source = str; source; source = va_arg(argList, const char *)) |
||||
bytes += StrLen(source); |
||||
va_end(argList); |
||||
} |
||||
|
||||
// Allocate string buffer
|
||||
char* packed = (char *) malloc(bytes); |
||||
|
||||
// Pack the string
|
||||
{ |
||||
va_list argList; |
||||
va_start(argList, str); |
||||
char * dest = packed; |
||||
for (const char * source = str; source; source = va_arg(argList, const char *)) |
||||
dest += StrCopyLen(dest, source, packed + bytes - dest); |
||||
va_end(argList); |
||||
} |
||||
|
||||
// Send the string
|
||||
AsyncSocketSend(sock, packed, bytes - 1); |
||||
|
||||
// Free the string
|
||||
free(packed); |
||||
} |
||||
|
||||
//===========================================================================
|
||||
static void IMail ( |
||||
const char * stepTable[], |
||||
const char smtp[], |
||||
const char sender[], |
||||
const char recipient[], |
||||
const char replyTo[], |
||||
const char subject[], |
||||
const char body[], |
||||
const char auth[], |
||||
EMailEncoding bodyEncoding, |
||||
FMailResult callback, |
||||
void * param |
||||
) { |
||||
static const char * utf8 = "\"utf-8\""; |
||||
const char * encodingStr; |
||||
|
||||
if (bodyEncoding == kMailEncodeUtf8) |
||||
encodingStr = utf8; |
||||
else |
||||
encodingStr = ""; |
||||
|
||||
// Calculate string lengths
|
||||
unsigned lenSmtp = StrLen(smtp); |
||||
unsigned lenSender = StrLen(sender); |
||||
unsigned lenRecipient = StrLen(recipient); |
||||
unsigned lenReplyTo = StrLen(replyTo); |
||||
unsigned lenSubject = StrLen(subject); |
||||
unsigned lenBodyEncoding = StrLen(encodingStr); |
||||
unsigned lenBody = StrLen(body); |
||||
unsigned lenAuth = StrLen(auth); |
||||
|
||||
// Calculate the required buffer size for all strings
|
||||
unsigned bytes = ( |
||||
lenSmtp + 1 + |
||||
lenSender + 1 + |
||||
lenRecipient + 1 + |
||||
lenReplyTo + 1 + |
||||
lenSubject + 1 + |
||||
lenBody + 1 + |
||||
lenAuth + 1 |
||||
) * sizeof(char); |
||||
|
||||
if (lenBodyEncoding) |
||||
bytes += (lenBodyEncoding + 1) * sizeof(char); |
||||
|
||||
// Create a transaction record
|
||||
MailTransaction * transaction = new( |
||||
malloc(offsetof(MailTransaction, buffer) + bytes) |
||||
) MailTransaction; |
||||
transaction->stepTable = stepTable; |
||||
transaction->sock = nil; |
||||
transaction->step = kMailStepConnect; |
||||
transaction->subStep = 0; |
||||
transaction->error = kMailSuccess; |
||||
transaction->callback = callback; |
||||
transaction->param = param; |
||||
|
||||
unsigned offset = 0; |
||||
transaction->smtp = transaction->buffer + offset; |
||||
offset += StrCopyLen(transaction->smtp, smtp, lenSmtp + 1) + 1; |
||||
transaction->sender = transaction->buffer + offset; |
||||
offset += StrCopyLen(transaction->sender, sender, lenSender + 1) + 1; |
||||
transaction->recipient = transaction->buffer + offset; |
||||
offset += StrCopyLen(transaction->recipient, recipient, lenRecipient + 1) + 1; |
||||
transaction->replyTo = transaction->buffer + offset; |
||||
offset += StrCopyLen(transaction->replyTo, replyTo, lenReplyTo + 1) + 1; |
||||
transaction->subject = transaction->buffer + offset; |
||||
offset += StrCopyLen(transaction->subject, subject, lenSubject + 1) + 1; |
||||
if (lenBodyEncoding) { |
||||
transaction->bodyEncoding = transaction->buffer + offset; |
||||
offset += StrCopyLen(transaction->bodyEncoding, encodingStr, lenBodyEncoding + 1) + 1; |
||||
} |
||||
else { |
||||
transaction->bodyEncoding = nil; |
||||
} |
||||
transaction->body = transaction->buffer + offset; |
||||
offset += StrCopyLen(transaction->body, body, lenBody + 1) + 1; |
||||
transaction->auth = transaction->buffer + offset; |
||||
offset += StrCopyLen(transaction->auth, auth, lenAuth + 1) + 1; |
||||
ASSERT(offset == bytes); |
||||
|
||||
// Start the transaction with a dns lookup
|
||||
const unsigned kSmtpPort = 25; |
||||
wchar_t smtpName[256]; |
||||
StrToUnicode(smtpName, smtp, arrsize(smtpName)); |
||||
|
||||
// Add transaction to global list
|
||||
bool shutdown; |
||||
s_critsect.Enter(); |
||||
{ |
||||
shutdown = s_shutdown; |
||||
s_mail.Link(transaction); |
||||
} |
||||
s_critsect.Leave(); |
||||
|
||||
if (shutdown) { |
||||
DestroyTransaction(transaction); |
||||
} |
||||
else { |
||||
NetAddress addr; |
||||
if (NetAddressFromString(&addr, smtpName, kSmtpPort)) { |
||||
AsyncCancelId cancelId; |
||||
AsyncSocketConnect( |
||||
&cancelId, |
||||
addr, |
||||
MailNotifyProc, |
||||
transaction |
||||
); |
||||
} |
||||
else { |
||||
AsyncCancelId cancelId; |
||||
AsyncAddressLookupName( |
||||
&cancelId, |
||||
MailLookupProc, |
||||
smtpName, |
||||
kSmtpPort, |
||||
transaction |
||||
); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/****************************************************************************
|
||||
* |
||||
* Exported functions |
||||
* |
||||
***/ |
||||
|
||||
//===========================================================================
|
||||
void MailEncodePassword ( |
||||
const char username[], |
||||
const char password[], |
||||
ARRAY(char) * emailAuth |
||||
) { |
||||
// base64_encode("\0#{user}\0#{secret}")
|
||||
emailAuth->Reserve(512); |
||||
emailAuth->Push(0); |
||||
emailAuth->Add(username, StrBytes(username)); |
||||
emailAuth->Add(password, StrBytes(password)); |
||||
unsigned srcChars = emailAuth->Bytes(); |
||||
|
||||
// Allocate space for encoded data
|
||||
unsigned dstChars = Base64EncodeSize(srcChars); |
||||
char * dstData = emailAuth->New(dstChars); |
||||
|
||||
// Encode data and move it back to the front of the array
|
||||
dstChars = Base64Encode( |
||||
srcChars, |
||||
(const uint8_t *) emailAuth->Ptr(), |
||||
dstChars, |
||||
dstData |
||||
); |
||||
emailAuth->Move( |
||||
0, |
||||
srcChars, |
||||
dstChars |
||||
); |
||||
emailAuth->SetCountFewer(dstChars); |
||||
} |
||||
|
||||
//===========================================================================
|
||||
void Mail ( |
||||
const char smtp[], |
||||
const char sender[], |
||||
const char recipient[], // multiple recipients separated by semicolons
|
||||
const char subject[], |
||||
const char body[], |
||||
const char username[], |
||||
const char password[], |
||||
const char replyTo[], |
||||
EMailEncoding bodyEncoding, |
||||
FMailResult callback, |
||||
void * param |
||||
) { |
||||
s_shutdown = false; |
||||
|
||||
// Get email authorization
|
||||
const char * auth; |
||||
const char ** stepTable; |
||||
ARRAY(char) authBuffer; |
||||
if (!password || !*password) { |
||||
// No password is specified, use non-authenticated email
|
||||
auth = ""; |
||||
stepTable = s_waitStrNoAuth; |
||||
} |
||||
else if (!username || !*username) { |
||||
// No username specified, user is providing the base64 encoded secret
|
||||
auth = password; |
||||
stepTable = s_waitStrAuth; |
||||
} |
||||
else { |
||||
MailEncodePassword(username, password, &authBuffer); |
||||
auth = authBuffer.Ptr(); |
||||
stepTable = s_waitStrAuth; |
||||
} |
||||
|
||||
IMail( |
||||
stepTable, |
||||
smtp, |
||||
sender, |
||||
recipient, |
||||
replyTo ? replyTo : "", |
||||
subject, |
||||
body, |
||||
auth, |
||||
bodyEncoding, |
||||
callback, |
||||
param |
||||
); |
||||
} |
||||
|
||||
//===========================================================================
|
||||
void MailStop () { |
||||
s_critsect.Enter(); |
||||
{ |
||||
s_shutdown = true; |
||||
MailTransaction * transaction = s_mail.Head(); |
||||
for (; transaction; transaction = s_mail.Next(transaction)) { |
||||
if (transaction->sock) |
||||
AsyncSocketDisconnect(transaction->sock, true); |
||||
transaction->error = kMailErrClientCanceled; |
||||
} |
||||
} |
||||
s_critsect.Leave(); |
||||
|
||||
AsyncAddressLookupCancel( |
||||
MailLookupProc, |
||||
0 // cancel all
|
||||
); |
||||
AsyncSocketConnectCancel( |
||||
MailNotifyProc, |
||||
0 // cancel all
|
||||
); |
||||
} |
||||
|
||||
//===========================================================================
|
||||
bool MailQueued () { |
||||
bool queued; |
||||
s_critsect.Enter(); |
||||
queued = s_mail.Head() != nil; |
||||
s_critsect.Leave(); |
||||
return queued; |
||||
} |
||||
|
||||
//============================================================================
|
||||
const wchar_t * MailErrorToString (EMailError error) { |
||||
|
||||
switch (error) { |
||||
case kMailSuccess: return L"kMailSuccess"; |
||||
case kMailErrDnsFailed: return L"kMailErrDnsFailed"; |
||||
case kMailErrConnectFailed: return L"kMailErrConnectFailed"; |
||||
case kMailErrDisconnected: return L"kMailErrDisconnected"; |
||||
case kMailErrClientCanceled: return L"kMailErrClientCanceled"; |
||||
case kMailErrServerError: return L"kMailErrServerError"; |
||||
DEFAULT_FATAL(error); |
||||
} |
||||
} |
@ -1,112 +0,0 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools |
||||
Copyright (C) 2011 Cyan Worlds, Inc. |
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7 |
||||
|
||||
If you modify this Program, or any covered work, by linking or |
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
||||
(or a modified version of those libraries), |
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
||||
licensors of this Program grant you additional |
||||
permission to convey the resulting work. Corresponding Source for a |
||||
non-source form of such a combination shall include the source code for |
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
||||
work. |
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
||||
or by snail mail at: |
||||
Cyan Worlds, Inc. |
||||
14617 N Newport Hwy |
||||
Mead, WA 99021 |
||||
|
||||
*==LICENSE==*/ |
||||
/*****************************************************************************
|
||||
* |
||||
* $/Plasma20/Sources/Plasma/NucleusLib/pnMail/pnMail.h |
||||
*
|
||||
***/ |
||||
|
||||
#ifndef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNMAIL_PNMAIL_H |
||||
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNMAIL_PNMAIL_H |
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* |
||||
* Mail API |
||||
* |
||||
***/ |
||||
|
||||
enum EMailEncoding { |
||||
kMailEncodeNone, |
||||
kMailEncodeAscii, |
||||
kMailEncodeUtf8, |
||||
}; |
||||
|
||||
enum EMailError { |
||||
kMailSuccess, |
||||
kMailErrDnsFailed, |
||||
kMailErrConnectFailed, |
||||
kMailErrDisconnected, |
||||
kMailErrClientCanceled, |
||||
kMailErrServerError, |
||||
}; |
||||
|
||||
|
||||
typedef void (* FMailResult)(void * param, EMailError result); |
||||
|
||||
|
||||
void MailStop (); |
||||
bool MailQueued (); |
||||
|
||||
const wchar_t * MailErrorToString (EMailError error); |
||||
|
||||
|
||||
//============================================================================
|
||||
// AUTHENTICATION NOTES
|
||||
// username, password
|
||||
// NULL NULL --> no authentication
|
||||
// NULL string --> username/password assumed to be pre-encoded with MailEncodePassword
|
||||
// string string --> username/password contain appropriate values for snmp server
|
||||
//============================================================================
|
||||
|
||||
void Mail ( |
||||
const char smtp[], |
||||
const char sender[], |
||||
const char recipients[], // separate multiple recipients with semicolons
|
||||
const char subject[], |
||||
const char body[], |
||||
const char username[], // optional (see auth notes above)
|
||||
const char password[], // optional (see auth notes above)
|
||||
const char replyTo[], // optional
|
||||
EMailEncoding encoding, |
||||
FMailResult callback, // optional
|
||||
void * param // optional
|
||||
); |
||||
|
||||
void MailEncodePassword ( |
||||
const char username[], |
||||
const char password[], |
||||
ARRAY(char) * emailAuth |
||||
); |
||||
|
||||
|
||||
#endif // PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNMAIL_PNMAIL_H
|
Loading…
Reference in new issue