📄 smtp.cpp
字号:
// ========================================================
// SMTP Protocol Handler
//
// Design and Implementation by Floris van den Berg
// ========================================================
#pragma warning (disable : 4275)
#pragma warning (disable : 4786)
#include <string>
#include "..\OpenNet.h"
#include "Cabinet.h"
// --------------------------------------------------------
class CSMTPProtocol : public IProtocol {
public :
CSMTPProtocol();
virtual unsigned long DLL_CALLCONV AddRef();
virtual unsigned long DLL_CALLCONV Release();
virtual HRESULT DLL_CALLCONV QueryInterface(REFIID guid, void **iif);
virtual void DLL_CALLCONV Initialize(TRANSPORT_HANDLE transport);
virtual void DLL_CALLCONV Receive(unsigned char *data, int size);
virtual void DLL_CALLCONV Send(EpAction *action);
virtual void DLL_CALLCONV Reset();
virtual int DLL_CALLCONV GetName(char *name, int size);
virtual int DLL_CALLCONV GetMessageName(int msg, char *name, int size);
private :
int m_ref_count;
TRANSPORT_HANDLE m_transport;
char data[8192];
int data_size;
int data_pos;
};
// --------------------------------------------------------
CSMTPProtocol::CSMTPProtocol() :
m_ref_count(0),
m_transport(NULL),
data(),
data_size(0),
data_pos(0) {
memset(&data, 0, sizeof(data));
}
unsigned long DLL_CALLCONV
CSMTPProtocol::AddRef() {
return ++m_ref_count;
}
unsigned long DLL_CALLCONV
CSMTPProtocol::Release() {
int ref_count = --m_ref_count;
if (ref_count == 0)
delete this;
return ref_count;
}
HRESULT DLL_CALLCONV
CSMTPProtocol::QueryInterface(REFIID guid, void **iif) {
if (IsEqualGUID(guid, CLSID_SYSTEM_PROTOCOL)) {
AddRef();
*iif = this;
return S_OK;
} else if (IsEqualGUID(guid, GUID_OBJECT)) {
AddRef();
*iif = this;
return S_OK;
}
return E_NOINTERFACE;
}
void DLL_CALLCONV
CSMTPProtocol::Initialize(TRANSPORT_HANDLE transport) {
m_transport = transport;
}
void DLL_CALLCONV
CSMTPProtocol::Receive(unsigned char *data, int size) {
// copy the data into the buffer
memcpy(data + data_size, data, size);
data_size += size;
// search for 0x0D's. if found we found a valid SMTP reply
int i = 0;
int pos = 0;
// strip any pending 0x0A and 0x0D chars
while (pos < data_size) {
if ((data[pos] != 0x0A) && (data[pos] != 0x0D))
break;
++pos;
}
// search for the next 0x0A or 0x0D
while (pos + i < data_size) {
if ((data[pos + i] == 0x0A) || (data[pos + i] == 0x0D)) {
int char_before_delimiter = (pos + i) - 4;
// search a bit further for more 0x0As or 0x0Ds
while (pos + i < data_size) {
if ((data[pos + i] != 0x0A) && (data[pos + i] != 0x0D))
break;
++i;
}
// grab the first number from the buffer
char number_ascii[4] = { 0, 0, 0, 0 };
memcpy(number_ascii, data + pos, 3);
// grab the message data
char msg_data[8192];
memset(msg_data, 0, 8192);
memcpy(msg_data, data + pos + 4, char_before_delimiter);
// allocate an em_transport event
EpEvent pm_event;
pm_event.reference_id = 0;
pm_event.protocol = CLSID_SMTP_PROTOCOL;
pm_event.size = strlen(msg_data) + 1;
pm_event.data = (unsigned char *)msg_data;
pm_event.reference_id = 0;
// post an event for the reply number
switch (atoi(number_ascii)) {
case 211 :
pm_event.msg = SMTP_REPLY_SYSTEM_STATUS;
break;
case 214 :
pm_event.msg = SMTP_REPLY_HELP_MESSAGE;
break;
case 220 :
pm_event.msg = SMTP_REPLY_SERVICE_READY;
break;
case 221 :
pm_event.msg = SMTP_REPLY_SERVICE_CLOSING;
break;
case 250 :
pm_event.msg = SMTP_REPLY_REQUESTED_MAIL_COMPLETED;
break;
case 251 :
pm_event.msg = SMTP_REPLY_USER_FORWARDED;
break;
case 354 :
pm_event.msg = SMTP_REPLY_START_MAIL_INPUT;
break;
case 421 :
pm_event.msg = SMTP_REPLY_SERVICE_NOT_AVAILABLE;
break;
case 450 :
pm_event.msg = SMTP_REPLY_MAILBOX_BUSY;
break;
case 451 :
pm_event.msg = SMTP_REPLY_LOCAL_ERROR_IN_PROCESSING;
break;
case 452 :
pm_event.msg = SMTP_REPLY_INSUFFICIENT_STORAGE;
break;
case 500 :
pm_event.msg = SMTP_REPLY_COMMAND_UNREGOGNIZED;
break;
case 501 :
pm_event.msg = SMTP_REPLY_INVALID_PARAMETERS;
break;
case 502 :
pm_event.msg = SMTP_REPLY_COMMAND_NOT_IMPLEMENTED;
break;
case 503 :
pm_event.msg = SMTP_REPLY_MAILBOX_UNAVAILABLE;
break;
case 504 :
pm_event.msg = SMTP_REPLY_PARAMETER_NOT_IMPLEMENTED;
break;
case 550 :
pm_event.msg = SMTP_REPLY_MAILBOX_UNAVAILABLE;
break;
case 551 :
pm_event.msg = SMTP_REPLY_USER_NOT_LOCAL;
break;
case 552 :
pm_event.msg = SMTP_REPLY_EXCEEDED_STORAGE_ALLOCATION;
break;
case 553 :
pm_event.msg = SMTP_REPLY_MAILBOX_NAME_NOT_ALLOWED;
break;
case 554 :
pm_event.msg = SMTP_REPLY_TRANSACTION_FAILED;
break;
};
// post event
EpDispatchEvent(m_transport, &pm_event);
// move message from queue
memcpy(data, data + i, data_size - i);
data_size -= i;
i = 0;
break;
} else {
++i;
}
}
}
void DLL_CALLCONV
CSMTPProtocol::Send(EpAction *action) {
switch(action->msg) {
case SMTP_MAIL_FROM :
{
_STL::string s = _STL::string("MAIL FROM:<") + _STL::string((char *)action->data) + _STL::string(">\r\n");
EpCompleteAction(m_transport, (unsigned char *)s.c_str(), s.length());
break;
}
};
}
void DLL_CALLCONV
CSMTPProtocol::Reset() {
data_size = 0;
data_pos = 0;
memset(&data, 0, sizeof(data));
}
int DLL_CALLCONV
CSMTPProtocol::GetName(char *name, int size) {
if (size >= 5)
strcpy(name, "SMTP");
return 5;
}
int DLL_CALLCONV
CSMTPProtocol::GetMessageName(int msg, char *name, int size) {
return 0;
}
// --------------------------------------------------------
// Instantation function
// --------------------------------------------------------
static HRESULT DLL_CALLCONV
SMTPProtocolCreate(void **iif) {
CSMTPProtocol *object = new CSMTPProtocol;
if (object) {
object->AddRef();
*iif = object;
return S_OK;
}
return E_FAIL;
}
// --------------------------------------------------------
// Discover function
// --------------------------------------------------------
void DLL_CALLCONV
SMTPProtocolInitialize() {
EpRegisterProtocol(CLSID_SMTP_PROTOCOL, SMTPProtocolCreate);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -