Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > отправка почты через proxy


Автор: kernell.cpp 12.10.2004, 11:20
Как отправить почту через прокси, используя smtp и не имея прокси клиента (например, ISA)?

Автор: Step 12.10.2004, 11:32
никак, прокся должна предусматривать тунелирования, а для этого она должна быть настроенна на твой ящик

короче геморойное это дело через проксю почту отпровлять...
практически не возможно без модификации настроек прокси

хотя если стоит вингейт то для твоей проги он прозрачен, отпровляй как обычно

Автор: kernell.cpp 12.10.2004, 11:41
А если своего клиента написать?
Я имею ввиду, что proxy-сервер установлен на серваке, а на узлах нет клиентской части. У пользователей explorer настроен на проксю и http нормально работает, а вот, smtp - нет.

Автор: Step 12.10.2004, 12:10
smtp
и pop3
отличаються от фтп и шттп и шттпс тем что в протоколе не предусмотренна передача адреса для конекта результатом чего являеться не возможность создания прокси-сервера(ну тут надо бы уточнить, но я опущу этот момент) для этих протоколов


Своего клиента писать не надо любой клиент будет работать согласно протоколам... как вы его не пишите, но вот если вы напишете тунель и установите его на сервер а потом перенестроете любую почтовую программу - вот единственный выход


я говорил уже про вин гейт.... его основное достоинства - что это действительно прокси сервер
прокси сервер согласно всем пунктам определения.... он являеться прозрачным для вас и не требует не каких настроек т.к. он подменяеть все функции работы с сетью , перехватывает параметры, конектиться свой сервер по своему протоколу и сервер согласно всем параметрам действует дальше....

Автор: Step 12.10.2004, 12:32
Могу подсказать пути написания тунеля

Автор: _hunter 12.10.2004, 12:38
это и я с удовольствием послушаю

Автор: Step 12.10.2004, 12:41
я бы вам код дал, но сегодня он погиб в 9 утра - райд массив дал глюк....

чуть по позже раскажу

Автор: _hunter 12.10.2004, 12:52
ок ( мне не к спеху, но для общего образования -- самое оно )

Автор: Step 12.10.2004, 12:54
ищите на следущей недели в факю или в рассылки..
Добавлено @ 12:54
я кстати свой тунель буду переделывать

Автор: kernell.cpp 12.10.2004, 13:01
2step:
Будешь писать код - кинь, пожалуйста, на почту. ([email protected])
Да, кстати, может можно попробовать через другой протокол, например - IMAP?

Автор: Step 12.10.2004, 13:05
smile.gif я подумаю

Автор: kernell.cpp 12.10.2004, 13:55
Есть полезная ссылка, может кому пригодится.
http://www.codeproject.com/internet/nishcsmtpproxymt.asp
М
 
Проверьте ссылку, похоже она не рабочая

Автор: kernell.cpp 13.10.2004, 14:42
Короче, даю код без комментов, просто нет времени расписывать. Прога позволяет слать мыло через прокси и не только, кто разберется - молодец!
Вот - ашник, в кот объявлены классы.

#include <winsock2.h>
#include <process.h>

#define OK_SUCCESS 0
#define ERR_RUNNING 1
#define ERR_WSAFAIL 2
#define ERR_INVALIDSOCKET 3
#define ERR_BIND 4
#define ERR_LISTEN 5
#define ERR_HOST 6
#define ERR_CONNECT 7
#define ERR_STOPPED 8


class CSmtpProxyMT
{
private:
struct SSmtp
{
char SmtpServer[250];
char ClientIP[20];
int SmtpPort;
int LocalPort;
SOCKET LocalSocket;
CSmtpProxyMT* pCSmtpProxyMT;
public:
void CopyStruct(SSmtp *pSSmtp);
};
struct socket_pair
{
SOCKET src;
SOCKET dest;
BOOL IsClient;
CSmtpProxyMT* pCSmtpProxyMT;
};

protected:
BOOL AcceptFlag;
SSmtp m_SSmtp;
SOCKET SmtpServerSocket;
char ProxySignature[2048];

public:
int StopProxy();
int StartProxy(char *server, int port, int localport);
CSmtpProxyMT();
virtual ~CSmtpProxyMT();
BOOL SetSignature(char *sig);

private:
static void AddToEnd(char* buff, char* b, char* sig);
static int InsertTextSignature(char*,char*);
static BOOL FoundBoundary(char *boundary, char *buff);
static BOOL IsEndOfData(char*);
static char * MakeUpper(char * );
static BOOL IsDataCommand(char *);
DWORD SmtpProxyThreadMain();
static DWORD SmtpProxyThread(DWORD arg);
void StartProxyThread(CSmtpProxyMT* m_pCSmtpProxyMT);
static DWORD SmtpClientThread(DWORD arg);
void StartClientThread(SSmtp *pSSmtp);
static DWORD SmtpDataThread(DWORD arg);
static void StartDataThread(socket_pair *pspair);

};

Добавлено @ 14:44
Вот - код:

#include "stdafx.h"
#include "SmtpProxyMT.h"


CSmtpProxyMT::CSmtpProxyMT()
{
AcceptFlag=false;
}

CSmtpProxyMT::~CSmtpProxyMT()
{

}

int CSmtpProxyMT::StartProxy(char *server, int port, int localport)
{
if(AcceptFlag)
return ERR_RUNNING;
strcpy(m_SSmtp.SmtpServer,server);
m_SSmtp.SmtpPort=port;
m_SSmtp.LocalPort=localport;
AcceptFlag=true;
StartProxyThread(this);
return 0;
}

void CSmtpProxyMT::StartProxyThread(CSmtpProxyMT* m_pCSmtpProxyMT)
{
SECURITY_ATTRIBUTES sa;
DWORD threadid=0;
sa.nLength=sizeof(sa);
sa.lpSecurityDescriptor=NULL;

_beginthreadex((void*)&sa,0,
(unsigned(__stdcall*)(void*))CSmtpProxyMT::SmtpProxyThread,
(void*)m_pCSmtpProxyMT,0,(unsigned int*)&threadid);

}

DWORD CSmtpProxyMT::SmtpProxyThread(DWORD arg)
{
CSmtpProxyMT* m_pCSmtpProxyMT=static_cast<CSmtpProxyMT*>((void*)arg);
return m_pCSmtpProxyMT->SmtpProxyThreadMain();
}

DWORD CSmtpProxyMT::SmtpProxyThreadMain()
{
WSADATA wsaData;
sockaddr_in local;
int wsaret=WSAStartup(0x101,&wsaData);
if(wsaret!=0)
{
return ERR_WSAFAIL;
}
local.sin_family=AF_INET;
local.sin_addr.s_addr=INADDR_ANY;
local.sin_port=htons((u_short)this->m_SSmtp.LocalPort);
SmtpServerSocket=socket(AF_INET,SOCK_STREAM,0);
if(SmtpServerSocket==INVALID_SOCKET)
{
return ERR_INVALIDSOCKET;
}
if(bind(SmtpServerSocket,(sockaddr*)&local,sizeof(local))!=0)
{
return ERR_BIND;
}
if(listen(SmtpServerSocket,10)!=0)
{
return ERR_LISTEN;
}

SOCKET SmtpClientSocket;
sockaddr_in from;
int fromlen=sizeof(from);

while(AcceptFlag)
{
char temp[250];
SmtpClientSocket=accept(SmtpServerSocket,
(struct sockaddr*)&from,&fromlen);
if(!AcceptFlag)
break;

sprintf(temp,"%s",inet_ntoa(from.sin_addr));
this->m_SSmtp.LocalSocket=SmtpClientSocket;
this->m_SSmtp.pCSmtpProxyMT=this;

SSmtp *pSSmtp = new SSmtp;
m_SSmtp.CopyStruct(pSSmtp);
StartClientThread(pSSmtp);

}

closesocket(SmtpServerSocket);
WSACleanup();

return 0;
}

void CSmtpProxyMT::SSmtp::CopyStruct(SSmtp *pSSmtp)
{
strcpy(pSSmtp->ClientIP,ClientIP);
pSSmtp->LocalPort=LocalPort;
pSSmtp->LocalSocket=LocalSocket;
pSSmtp->SmtpPort=SmtpPort;
strcpy(pSSmtp->SmtpServer,SmtpServer);
pSSmtp->pCSmtpProxyMT=pCSmtpProxyMT;

}
void CSmtpProxyMT::StartClientThread(SSmtp *pSSmtp)
{
SECURITY_ATTRIBUTES sa;
DWORD threadid=0;
sa.nLength=sizeof(sa);
sa.lpSecurityDescriptor=NULL;

_beginthreadex((void*)&sa,0,
(unsigned(__stdcall*)(void*))CSmtpProxyMT::SmtpClientThread,
(void*)pSSmtp,0,(unsigned int*)&threadid);
}

DWORD CSmtpProxyMT::SmtpClientThread(DWORD arg)
{
SSmtp* pSSmtp=static_cast<SSmtp*>((void*)arg);
SOCKET conn;
struct hostent *hp;
unsigned int addr;
struct sockaddr_in smtp_server;
conn=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(inet_addr((char far*)pSSmtp->SmtpServer)==INADDR_NONE)
{
hp=gethostbyname(pSSmtp->SmtpServer);
}
else
{
addr=inet_addr(pSSmtp->SmtpServer);
hp=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET);
}
if(hp==NULL)
{
closesocket(conn);
closesocket(pSSmtp->LocalSocket);
delete pSSmtp;
return ERR_HOST;
}
smtp_server.sin_addr.s_addr=*((unsigned long*)hp->h_addr);
smtp_server.sin_family=AF_INET;
smtp_server.sin_port=htons(pSSmtp->SmtpPort);

if(connect(conn,(struct sockaddr*)&smtp_server,sizeof(smtp_server)))
{
closesocket(conn);
closesocket(pSSmtp->LocalSocket);
delete pSSmtp;
return ERR_CONNECT;
}

socket_pair *fromClient=new socket_pair;
socket_pair *fromServer=new socket_pair;

fromClient->src=fromServer->dest=pSSmtp->LocalSocket;
fromClient->dest=fromServer->src=conn;
fromClient->IsClient=true;
fromServer->IsClient=false;
fromServer->pCSmtpProxyMT=fromClient->pCSmtpProxyMT=pSSmtp->pCSmtpProxyMT;
StartDataThread(fromClient);
StartDataThread(fromServer);

delete pSSmtp;
return 0;
}


void CSmtpProxyMT::StartDataThread(socket_pair *pspair)
{
SECURITY_ATTRIBUTES sa;
DWORD threadid=0;
sa.nLength=sizeof(sa);
sa.lpSecurityDescriptor=NULL;

_beginthreadex((void*)&sa,0,
(unsigned(__stdcall*)(void*))CSmtpProxyMT::SmtpDataThread,
(void*)pspair,0,(unsigned int*)&threadid);
}

DWORD CSmtpProxyMT::SmtpDataThread(DWORD arg)
{
socket_pair* pspair=static_cast<socket_pair*>((void*)arg);
char *buff=new char[10240+5120];
int n;
int data_stage=0;
BOOL ExistsBoundary=false;
char *boundary=new char[512];
BOOL alternate=false;
BOOL mixed=false;
while((n=recv(pspair->src,buff,10240,0))>0)
{
if(pspair->IsClient)
{
buff[n]=0;
if(data_stage==3)
{
char *tmpbuff=new char[10240+5120];
strcpy(tmpbuff,buff);
if(strstr(MakeUpper(tmpbuff),"MAIL FROM:")!=NULL)
{
data_stage=0;
ExistsBoundary=false;
alternate=false;
mixed=false;
}
delete tmpbuff;
}
if(data_stage==0)
if(IsDataCommand(buff))
data_stage=1;
if(data_stage==1)
{
if(!alternate)
{
if(strstr(buff,"Content-Type: multipart/alternative")!=NULL)
alternate=true;
}
if(!mixed)
{
if(strstr(buff,"Content-Type: multipart/mixed")!=NULL)
mixed=true;
}
if(!ExistsBoundary)
ExistsBoundary=FoundBoundary(boundary,buff);
if(ExistsBoundary)
{
if(alternate && !mixed)
{
char boundary1[512+64];
strcpy(boundary1,"\r\n--");
strcat(boundary1,boundary);
int i1=strlen(buff);
AddToEnd(buff, boundary1,pspair->pCSmtpProxyMT->ProxySignature);
n+=(strlen(buff)-i1);
}
else
{
char boundary1[512+64];
strcpy(boundary1,"\r\n--");
strcat(boundary1,boundary);
strcat(boundary1,"--\r\n");
char *p1;
char *p2;
char *buff2=new char[10240+5120];
char *buff3=new char[10240+5120];
strcpy(buff2,buff);
strcpy(buff3,buff);
if((p1=strstr(buff2,boundary1))!=NULL)
{

char sig[2048+512+512+128];
strcpy(sig,"\r\n--");
strcat(sig,boundary);
strcat(sig,"\r\n");
strcat(sig,"Content-Type: text/plain;\r\n\r\n");
strcat(sig,pspair->pCSmtpProxyMT->ProxySignature);
strcat(sig,"\r\n--");
strcat(sig,boundary);
strcat(sig,"\r\n\r\n");
p2=strstr(buff3,boundary1);
*p1=0;

strcat(buff2,sig);
strcat(buff2,p2);
n+=(strlen(buff2)-strlen(buff));
strcpy(buff,buff2);
}
delete buff2;
delete buff3;
}
}
if(IsEndOfData(buff))
data_stage=2;
}
if(data_stage==2)
{
if(!ExistsBoundary)
{
n+=InsertTextSignature(buff,pspair->pCSmtpProxyMT->ProxySignature);
}
data_stage=3;
}

}
send(pspair->dest,buff,n,0);
}
shutdown(pspair->src,SD_BOTH);
closesocket(pspair->src);
shutdown(pspair->dest,SD_BOTH);
closesocket(pspair->dest);
delete boundary;
delete buff;
delete pspair;
return 0;
}

BOOL CSmtpProxyMT::IsDataCommand(char *str)
{
char *str1=new char[10240+5120];
BOOL rv;
strcpy(str1,str);
if(strcmp(MakeUpper(str1),"DATA\r\n")==0)
rv= true;
else
rv= false;
delete str1;
return rv;
}

char* CSmtpProxyMT::MakeUpper(char* str)
{
char* tmp=str;
while(*tmp)
{
if(islower(*tmp))
*tmp=_toupper(*tmp);
tmp++;
}
return str;
}

BOOL CSmtpProxyMT::IsEndOfData(char *str)
{
if(strstr(str,"\r\n.\r\n")!=NULL)
return true;
else
return false;
}

BOOL CSmtpProxyMT::FoundBoundary(char *boundary, char *buff)
{
char *buff1=new char[10240+5120];
strcpy(buff1,buff);
char *tmp=strstr(buff1,"boundary=\"");
if(tmp==NULL)
{
delete buff1;
return false;
}
tmp+=10;
char *tmp1=strstr(tmp,"\"\r\n");
if(tmp1==NULL)
{
delete buff1;
return false;
}
*tmp1=0;
strcpy(boundary,tmp);
delete buff1;
return true;
}

int CSmtpProxyMT::InsertTextSignature(char *buff, char* sig)
{
char *tmp=strstr(buff,"\r\n.\r\n");
*tmp=0;
strcat(buff,sig);
strcat(buff,"\r\n.\r\n");
return strlen(sig);
}


BOOL CSmtpProxyMT::SetSignature(char *sig)
{
if(strlen(sig)>2047)
return false;
strcpy(ProxySignature,sig);
return true;
}


void CSmtpProxyMT::AddToEnd(char *buff, char *b, char* sig)
{
char *newbuff1=new char[10240+5120];
char *newbuff2=new char[10240+5120];
strcpy(newbuff1,buff);
char *p1;
int skip=1;
for(int i=0;i<=1;i++)
{
p1=newbuff1;
for(int j=0;j<skip;j++)
{
p1=strstr(p1,b);
if(p1==NULL)
{
delete newbuff1;
delete newbuff2;
return;
}
p1++;
}
p1=strstr(p1,b);
if(p1==NULL)
{
delete newbuff1;
delete newbuff2;
return;
}
strcpy(newbuff2,p1);
*p1=0;
strcat(newbuff1,sig);
strcat(newbuff1,newbuff2);
skip++;
}

strcpy(buff,newbuff1);

delete newbuff1;
delete newbuff2;
}

int CSmtpProxyMT::StopProxy()
{
if(!AcceptFlag)
return ERR_STOPPED;
AcceptFlag=false;
closesocket(SmtpServerSocket);
return OK_SUCCESS;
}

Добавлено @ 14:50
Что необходимо сделать:
1) Надо вставить библиотеку (#pragma comment (lib, "ws2_32.lib")
2) объявляем переменную
CSmtpProxyMT *m_smtpproxy;
3) создаем объект
m_smtpproxy = new CSmtpProxyMT;
4) можно инкапсулировать сигнатуру в мыло
m_smtpproxy->SetSignature("Hello World");
5) запускаем прокси
m_smtpproxy->StartProxy("192.168.1.44",25,125);
6) останавливаем прокси
m_smtpproxy->StopProxy();

Признаюсь, я как следует еще не протестил, но работать должно.
Все комменты и вопросы пишите здесь, по возможности отвечу.

Автор: Step 13.10.2004, 15:12
источник дай....

врядли оно будет работать так как нету параметров конекта на внешний

Автор: kernell.cpp 13.10.2004, 15:17
2Step:
В структуре SSmtp посмотри.
Источник я дал и у меня ссылка нормально работает, попробуй по ней последовательно пройти.
Добавлено @ 15:23
Да, прога письма сама не отправляет. После ее запуска можно настроить Bat и отсылать.

Автор: Step 13.10.2004, 15:26
Примерно начал понимать.... посмотрю

Автор: kernell.cpp 19.10.2004, 10:14
2step: Как считаешь, outlook and thebat забирают инфу из реестра о настройках proxy?
Или они используют только свои локальные настройки? У меня стоит ISA и в bat-е я не приписывал настройки proxy, клиент тоже установлен на машине и настроен на сервак.
ISA сам распознает типы пакетов, как думаешь? Я пробовал отключать клиента - почта не отсылается, т.к., видимо, открыт только 80 и 1900 порт.

Автор: Step 19.10.2004, 16:59
kernell.cpp, в том то и дело что им это не нужно.. так как эти данные им ничего не дадут
не забирают просто при пускании этих протоколов через проксю на закладке серверы выставляються адресса прокси... и оутлук думает что конектиться на сервак локальной сети но на самом деле прокся переадресовывает на глобальную

вообщем я уже начал писать, скоро будет результат
а что такое 1900 порт...

Автор: kernell.cpp 20.10.2004, 09:21
2step: 1900 порт - это порт обмена служебной информации прокси ISA.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)