?? mailer_class.cpp.svn-base
字號:
if(p != std::string::npos) { p += 1; // get past folder delimiter fn = fn.substr(p, fn.length()-p); } std::vector<std::pair<std::vector<char>, std::string> >::iterator it; for(it=attachments.begin(); it<attachments.end(); ++it) { if((*it).second == fn) { attachments.erase(it); return true; } } return false;}/* returns everything after the '@' in an email address * if there is no @, returns the empty string */std::string Mailer::getserveraddress(const std::string &toaddress) const{ if(toaddress.length()) { std::string::size_type pos(toaddress.find("@")); if(pos != std::string::npos) { // found the server beginning if(++pos < toaddress.length()) { return toaddress.substr(pos, toaddress.length() - pos); } } } return "";}/* this function has to get an MX record for 'server' and return its address */bool Mailer::gethostaddresses(std::vector<SOCKADDR_IN> &adds){ adds.clear(); // sure is sure ;) SOCKADDR_IN addr(nameserver, htons(DNS_PORT), AF_INET); hostent *host = 0; if(addr) { host = gethostbyaddr(addr.get_sin_addr(), sizeof(addr.ADDR.sin_addr), AF_INET); } else { host = gethostbyname(nameserver.c_str()); } if(!host) { addr = SOCKADDR_IN(server, port); addr.ADDR.sin_port = port; // smtp port if(addr) { host = gethostbyaddr(addr.get_sin_addr(), sizeof(addr.ADDR.sin_addr), AF_INET); } else { host = gethostbyname(server.c_str()); } if(!host) { returnstring = "550 Requested action not taken: mailbox unavailable"; return false; } std::copy(host->h_addr_list[0], host->h_addr_list[0] + host->h_length, addr.get_sin_addr()); adds.push_back(addr); return true; } else { std::copy(host->h_addr_list[0], host->h_addr_list[0] + host->h_length, addr.get_sin_addr()); } SOCKET s; if(!Socket(s, AF_INET, SOCK_DGRAM, 0)) { returnstring = "451 Requested action aborted: socket function error"; return false; } if(!Connect(s, addr)) { returnstring = "451 Requested action aborted: dns server unavailable"; return false; } unsigned char dns[512] = {1,1, 1,0, 0,1, 0,0, 0,0, 0,0}; int dnspos = 12; // end of dns header std::string::size_type stringpos(0); std::string::size_type next(server.find(".")); if(next != std::string::npos) { // multipart name while(stringpos < server.length()) { std::string part(server.substr(stringpos, next - stringpos)); dns[dnspos] = part.length(); ++dnspos; for(std::string::size_type i=0; i<part.length(); ++i, ++dnspos) { dns[dnspos] = part[i]; } stringpos = ++next; next = server.find(".", stringpos); if(next == std::string::npos) { part = server.substr(stringpos, server.length() - stringpos); dns[dnspos] = part.length(); ++dnspos; for(std::string::size_type i=0; i<part.length(); ++i, ++dnspos) { dns[dnspos] = part[i]; } break; } } } /* in case the server string has a dot on the end */ if(server[server.length()-1] == '.') { dns[dnspos] = 0; } else { dns[dnspos++] = 0; } /* add the class and type */ dns[dnspos++] = 0; dns[dnspos++] = 15; // MX record dns[dnspos++] = 0; dns[dnspos++] = 1; /* used to have MSG_DONTROUTE this breaks obviously if you are not running a local nameserver */ int ret; if(!Send(ret, s, (char *)dns, dnspos, 0)) { returnstring = "451 Requested action aborted: server seems to have disconnected."; return false; } if(Recv(ret, s, (char *)dns, 512, 0)) { Closesocket(s); /* now parse the data sent back from the dns for MX records */ if(dnspos > 12) { // we got more than a dns header back unsigned short numsitenames = ((unsigned short)dns[4] << 8) | dns[5]; unsigned short numanswerRR = ((unsigned short)dns[6] << 8) | dns[7]; unsigned short numauthorityRR = ((unsigned short)dns[8]<<8) | dns[9]; unsigned short numadditionalRR = ((unsigned short)dns[10]<<8) | dns[11]; if(!(dns[3] & 0x0F)) { // check for an error int pos = 12; // start after the header std::string questionname; if(numsitenames) { parsename(pos, dns, questionname); pos += 4; // move to next RR } std::vector<std::string> names; in_addr address; std::string name; int num = 0; for(; num < numanswerRR; ++num) { name = ""; parseRR(pos, dns, name, address); if(name.length()) names.push_back(name); } for(num = 0; num < numauthorityRR; ++num) { name = ""; parseRR(pos, dns, name, address); if(name.length()) names.push_back(name); } for(num = 0; num < numadditionalRR; ++num) { name = ""; parseRR(pos, dns, name, address); if(name.length()) names.push_back(name); } /* now get all the MX records IP addresses */ addr.ADDR.sin_family = AF_INET; addr.ADDR.sin_port = port; // smtp port 25 hostent *host = 0; for(vec_str_const_iter it=names.begin(); it<names.end(); ++it) { host = gethostbyname(it->c_str()); if(!host) { addr.zeroaddress(); continue; // just skip it } std::copy(host->h_addr_list[0], host->h_addr_list[0] + host->h_length, addr.get_sin_addr()); adds.push_back(addr); } /* got the addresses */ return true; } } } else { Closesocket(s); } return false; // this code should never be reached}bool Mailer::parseRR(int &pos, const unsigned char dns[], std::string &name, in_addr &address){ if(pos < 12) { // didn't get more than one header return false; } if(pos > 512) { // oops return false; } int len = dns[pos]; if(len >= 192) { // pointer int pos1 = dns[++pos]; len = dns[pos1]; } else { // not a pointer parsename(pos, dns, name); } unsigned short a = ((unsigned short)dns[++pos] << 8); unsigned short b = dns[++pos]; unsigned short type = a | b; a = ((unsigned short)dns[++pos] << 8); b = dns[++pos]; pos += 4; // ttl a = ((unsigned short)dns[++pos] << 8); b = dns[++pos]; unsigned short datalen = a | b; if(type == 15) { // mx record /* first two bytes are the precedence of the MX record */ a = ((unsigned short)dns[++pos] << 8); b = dns[++pos]; len = dns[++pos]; if(len >= 192) { int pos1 = dns[++pos]; parsename(pos1, dns, name); } else { parsename(pos, dns, name); } } else { pos += datalen + 1; } return true;}/* parse the recipient name */void Mailer::parsename(int &pos, const unsigned char dns[], std::string &name) { int len = dns[pos]; if(len >= 192) { int pos1 = ++pos; ++pos; parsename(pos1, dns, name); } else { for(int i = 0; i < len; ++i) name += dns[++pos]; len = dns[++pos]; if(len != 0) { name += "."; } if(len >= 192) { int pos1 = dns[++pos]; ++pos; parsename(pos1, dns, name); } else if(len > 0) { parsename(pos, dns, name); } else if(len == 0) { ++pos; } }}/* give us the returnstring from the server */const std::string &Mailer::response() const { return returnstring;}/* parse email adress */Mailer::Address Mailer::parseaddress(const std::string &addresstoparse){ Address newaddress; // return value if(!addresstoparse.length()) { return newaddress; // it's empty } if(!addresstoparse.find("@") == std::string::npos) { /* no @ symbol, could be a local address so assume this */ newaddress.address = addresstoparse; return newaddress; } /* we have one angle bracket but not the other one */ if(((addresstoparse.find('<') != std::string::npos) && (addresstoparse.find('>') == std::string::npos)) || ((addresstoparse.find('>') != std::string::npos) && (addresstoparse.find('<') == std::string::npos))) { return newaddress; } /* we have angle bracketed delimitered address */ if((addresstoparse.find('<') != std::string::npos) && (addresstoparse.find('>') != std::string::npos)) { std::string::size_type sta = addresstoparse.find('<'); std::string::size_type end = addresstoparse.find('>'); newaddress.address = addresstoparse.substr(sta+1, end - sta - 1); if(sta > 0) { // name at the beginning /* we are cutting off the last character if the bracket address continues * without a space into the bracketed address */ newaddress.name = addresstoparse.substr(0, sta); return newaddress; } else { // name at the end if(end >= addresstoparse.length() - 1) { return newaddress; } end += 2; if(end >= addresstoparse.length()) { return newaddress; } newaddress.name = addresstoparse.substr(end, addresstoparse.length() - end); if(newaddress.name[newaddress.name.length()-1] == ' ') { newaddress.name = newaddress.name.substr(0, newaddress.name.length() - 1); } return newaddress; } } /* if we get here, assume an address of the form: foo@bar.com and save it */ newaddress.address = addresstoparse; return newaddress;}/* set the authentification type */void Mailer::authtype(const enum authtype Type){ assert(Type == LOGIN || Type == PLAIN); type = Type;}/* set the username for authentification * * if this function is called with a non-empty string, we will try to use authentification */void Mailer::username(const std::string &User) { auth = (User.length() != 0); user = User;}/* set the password for authentification */void Mailer::password(const std::string &Pass){ pass = Pass;}/* authenticate against the server */bool Mailer::authenticate(const std::string &servergreeting, const SOCKET &s){ assert(auth && user.length()); int len(0); if(!user.length()) { Send(len, s, "QUIT\r\n", 6, 0); return false; } /* parse the server greeting looking for the auth type 'type'; * if 'type' isn't present, exit with an error (return false) */ std::string at; if(type == LOGIN) { at = "LOGIN"; } else if(type == PLAIN) { at = "PLAIN"; } else { // no other auth types supported yet assert(false); returnstring = "554 bitmailer only can handle LOGIN and PLAIN authentification"; Send(len, s, "QUIT\r\n", 6, 0); return false; } /* uppercase server greeting first */ std::string greeting(servergreeting); for(std::string::size_type pos=0; pos<greeting.length(); ++pos) { greeting[pos] = toupper(greeting[pos]); } if(greeting.find(at) == std::string::npos) { returnstring = "554 bitmailer only handles LOGIN and PLAIN authentification"; Send(len, s, "QUIT\r\n", 6, 0); return false; // didn't find that type of login } /* try and authenticate to the server */ const int buffsize(1024); char buff[buffsize]; if(type == LOGIN) { // login authentification greeting = "auth " + at + "\r\n"; if(!Send(len, s, greeting.c_str(), greeting.length(), 0)) { returnstring = "554 send failure: \"auth " + at + "\""; return false; } if(!Recv(len, s, buff, buffsize, 0)) { returnstring = "554 receive failure: waiting on username question!"; return false; } buff[len] = '\0'; returnstring = buff; /* server should give us a "334 VXNlcm5hbWU6" base64 username */ if(returnstring.substr(0, 16) != "334 VXNlcm5hbWU6") { Send(len, s, "QUIT\r\n", 6, 0); return false; } greeting = base64encode(user, false) + "\r\n"; if(!Send(len, s, greeting.c_str(), greeting.length(), 0)) { returnstring = "554 send failure: sending username"; return false; } /* now get the password question */ if(!Recv(len, s, buff, buffsize, 0)) { returnstring = "554 receive failure: waiting on password question"; return false; } buff[len] = '\0'; returnstring = buff; /* server should give us a "334 UGFzc3dvcmQ6" base64 password */ if(returnstring.substr(0, 16) != "334 UGFzc3dvcmQ6") { Send(len, s, "QUIT\r\n", 6, 0); return false; } greeting = base64encode(pass, false) + "\r\n"; if(!Send(len, s, greeting.c_str(), greeting.length(), 0)) { returnstring = "554 send failure: sending password"; return false; } if(!Recv(len, s, buff, buffsize, 0)) { returnstring = "554 receive failure: waiting on auth login response"; return false; } buff[len] = '\0'; returnstring = buff; if(returnstring.substr(0, 3) == "235") { return true; } } else if(type == PLAIN) { // plain authentication /* create the authentification response and send it */ std::vector<char> enc; std::string::size_type pos = 0; for( ; pos<user.length(); ++pos) { enc.push_back(user[pos]); } enc.push_back('\0'); for(pos=0; pos<user.length(); ++pos) { enc.push_back(user[pos]); } enc.push_back('\0'); for(pos=0; pos<pass.length(); ++pos) { enc.push_back(pass[pos]); } enc = base64encode(enc, false); greeting = "auth plain "; for(std::vector<char>::const_iterator it1=enc.begin(); it1<enc.end(); ++it1) { greeting += *it1; } greeting += "\r\n"; if(!Send(len, s, greeting.c_str(), greeting.length(), 0)) { returnstring = "554 send failure: sending login:plain authinfo"; return false; } if(!Recv(len, s, buff, buffsize, 0)) { returnstring = "554 receive failure: waiting on auth plain authenticated response"; return false; } buff[len] = '\0'; returnstring = buff; if(returnstring.substr(0, 3) == "235") { return true; } } /* fall through, return an error */ Send(len, s, "QUIT\r\n", 6, 0); return false;}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -