Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/email/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets 邮件提交代理(MSA)服务器主机名通过c++;_Sockets_Email_Resolve_Smtps - Fatal编程技术网

Sockets 邮件提交代理(MSA)服务器主机名通过c++;

Sockets 邮件提交代理(MSA)服务器主机名通过c++;,sockets,email,resolve,smtps,Sockets,Email,Resolve,Smtps,我正在寻找一种获取邮件提交服务器主机名的通用方法,方法是只使用c/c++的电子邮件地址,这样我就可以连接到端口587和/或465 smtp提交 例如。example@gmail.com->smtp.gmail.com或gmail-smtp-msa.l.google.com 基本上我是代表客户发送一些特定的电子邮件。所以最后看起来他们已经发送了电子邮件。到目前为止,我仍然在使用一个简单的域名到主机名映射,如{gmail.com,smtp.gmail.com},我会在需要时扩展它。但是,我非常希望避

我正在寻找一种获取邮件提交服务器主机名的通用方法,方法是只使用c/c++的电子邮件地址,这样我就可以连接到端口587和/或465 smtp提交

例如。example@gmail.com->smtp.gmail.com或gmail-smtp-msa.l.google.com

基本上我是代表客户发送一些特定的电子邮件。所以最后看起来他们已经发送了电子邮件。到目前为止,我仍然在使用一个简单的域名到主机名映射,如{gmail.com,smtp.gmail.com},我会在需要时扩展它。但是,我非常希望避免使用此地图,并将此过程自动化

前一段时间我发了帖子,应该是同一个问题,可能不够清楚。在回答中,我被建议执行DNS查找并请求MX记录。在一本书和一个实现之后,我注意到这些mx记录不适合邮件提交(无法连接到端口587,只有25个)。我检查了resolv.h中定义的所有其他类型,并检查了nslookup(无论如何可能使用resolv.h),到目前为止,我真的认为通过DNS查找是不可行的。如果有人想尝试,请选中
nslookup-type=mx gmail.com
您将不会看到任何-msa。。。东西

我现在有点绝望,因为我真的想把它完成。但是我也不想在这上面花上几个星期。如果有人告诉我这在合理的时间内是不可行的,我也会非常高兴


编辑:

下面是一个简单的例子,我刚刚通过DNS MX方法非常快速地实现了连接,并尝试连接到端口25465587

/*c++1z, Don't forget -lresolv*/
#include <resolv.h>
#include <string>
#include <map>
#include <sstream>
#include <cerrno>
#include <netdb.h>
#include <iostream>
#include <cstddef>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <fcntl.h>
#include <netinet/tcp.h>

//like assert but throws instead
#define CHECK(condition)\
    if(!(condition)){\
        std::ostringstream oss;\
        oss << __FILE__ << ":" << __LINE__ << "\nerrno:" << errno << "\nh_errno:" << h_errno << std::endl;\
        throw std::runtime_error(oss.str());\
    }

//!
//! \brief mxRecords performs dns T_MX lookup
//! \param domain the domain part of the email e.g. example@gmail.com -> gmail.com
//! \return multimap of {priority, server hostname} pairs
//!
auto mxRecords(std::string const&domain)
->std::multimap<size_t/*priority*/,std::string/*server name*/>
{
    std::basic_string<unsigned char> response(PACKETSZ,'0');
    int response_size = res_search(domain.data(),C_IN,T_MX,response.data(),response.size());
    CHECK(response_size != -1);
    response.resize(response_size);

    ns_msg handle;
    CHECK(ns_initparse(response.data(),response.size(),&handle) != -1);

    std::multimap<size_t,std::string> ret;
    for(int i = 0; i < ns_msg_count(handle,ns_s_an); ++i)
    {
        ns_rr rr;
        if(ns_parserr(&handle,ns_s_an,i,&rr) == -1)
            continue;
        if(ns_rr_type(rr) != ns_t_mx)
            continue;
        std::string exp_dn(MAXDNAME,0);
        if(ns_name_uncompress(ns_msg_base(handle),ns_msg_end(handle),ns_rr_rdata(rr)+NS_INT16SZ,exp_dn.data(),exp_dn.size()) == -1)
            continue;
        ret.emplace(ns_get16(ns_rr_rdata(rr)),exp_dn.data());
    }
    return ret;
}
bool __connect(std::string const&host, std::string const&port)
{
    addrinfo const __req{0,AF_UNSPEC,SOCK_STREAM,IPPROTO_TCP,0,nullptr,nullptr,nullptr};
    addrinfo *__pai(nullptr);
    if(getaddrinfo(host.data(),port.data(),&__req,&__pai) != 0)
        return false;
    for(addrinfo *iter = __pai; iter != nullptr; iter = iter->ai_next)
    {
        int fd = socket(iter->ai_family, iter->ai_socktype, iter->ai_protocol);
        if(fd == -1)
            continue;
        int retries = 1;
        setsockopt(fd, IPPROTO_TCP, TCP_SYNCNT, &retries, sizeof(retries));
        if(::connect(fd, iter->ai_addr, iter->ai_addrlen) == -1)
        {
            close(fd);
            continue;
        }
        freeaddrinfo(__pai);
        close(fd);
        return true;
    }
    freeaddrinfo(__pai);
    return false;
}
int main()
{
    std::string domain = "gmail.com";

    //get mx records and try to connect for port 25,465,587
    auto mx_records = mxRecords(domain);
    std::cout << "----------MX RECORDS <priority|host|port25|port465|port587> for " << domain << std::endl;
    for(auto iter = mx_records.begin(); iter != mx_records.end(); ++iter)
    {
        std::cout << iter->first << " | " << iter->second;
        //try port 25|port 465 | port 587
        for(auto port : {"25","465","587"})
        {
            if(__connect(iter->second,port))
                std::cout << " | y";
            else
                std::cout << " | n";
        }
        std::cout << std::endl;
    }
    return 0;
}
PORT-587

S:220 smtp.gmail.com ESMTP ############### - gsmtp
C:EHLO ###############
S:250-smtp.gmail.com at your service, ###############
  250-SIZE 35882577
  250-8BITMIME
  250-STARTTLS
  250-ENHANCEDSTATUSCODES
  250-PIPELINING
  250-CHUNKING
  250 SMTPUTF8
C:STARTTLS
S:220 2.0.0 Ready to start TLS
C:EHLO ###############
S:250-smtp.gmail.com at your service, ###############
  250-SIZE 35882577
  250-8BITMIME
  250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH
  250-ENHANCEDSTATUSCODES
  250-PIPELINING
  250-CHUNKING
  250 SMTPUTF8
C:QUIT
S:221 2.0.0 closing connection ############### - gsmtp
PORT-465

S:220 smtp.gmail.com ESMTP ############### - gsmtp
C:EHLO ###############
S:250-smtp.gmail.com at your service, ###############
  250-SIZE 35882577
  250-8BITMIME
  250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH
  250-ENHANCEDSTATUSCODES
  250-PIPELINING
  250-CHUNKING
  250 SMTPUTF8
C:QUIT
S:221 2.0.0 closing connection ############### - gsmtp

这在技术上不需要支持,但根据,您应该在
\u tcp
子域中查询
\u提交
主机的SRV记录,如下所示:

$ nslookup -type=srv _submission._tcp.gmail.com
Server:  google-public-dns-a.google.com
Address:  8.8.8.8

Non-authoritative answer:
_submission._tcp.gmail.com      SRV service location:
          priority       = 5
          weight         = 0
          port           = 587
          svr hostname   = smtp.gmail.com
有些事情你应该记住:

  • 从某种意义上说,这是一种“便利性特征”。如果您有电子邮件地址
    myname@acme.com
    ,则acme.com可能(也可能不)在
    \u tcp.acme.com
    中公开这些RFC 6186记录,以允许其用户的邮件客户端程序自动发现诸如POP3、IMAP等服务
  • 连接到域MSA可能会受到特殊限制。例如,服务可能只是拒绝来自
    xyz.com
    内部网络之外的机器的连接,或者需要内部可信证书,等等。MSA用于与邮件客户端MUA交互,而不是用于普通邮件传递

  • 这个答案是我给你们的,我之前所说的仍然适用于这个问题。是的,您对电子邮件域的MX记录执行DNS查找。这就是如何发现SMTP服务器的地址,然后可以使用TCP正常连接到该地址。该端口不由DNS处理,这就是为什么您在DNS数据中看不到它的原因。根据是否需要通过隐式SSL(端口465)、显式TLS(端口25或587,使用
    STARTTLS
    命令)与SMTP服务器通信,您可以决定连接到哪个端口。@RemyLebeau再次感谢您尝试帮助我!我在答案中包括了一个例子,它是按照你上一个答案中的建议来做的。我认为mx记录中列出的这些服务器不是为其他端口开放的,而是为25个端口开放的。我已经删除了“c++”标签,它似乎与此无关。我不知道为什么这被否决了。在我看来,这是一个非常有效的技术问题,我把它投了更高的票,所以你回到了0:)。此外,否决票通常应该给出一个理由。@RemyLebeau,OP代表客户行事,因此在这种情况下,假装是MUA是有理由的。你的答案是正确的,但这是对另一个问题的回答。在SaaS世界中,一切都是颠倒的而我,作为SaaS提供商公司的一员,当然也表示同情;众所周知,客户端更改其网络配置时不会三思而后行通知其合作伙伴。@kkm问题多次被否决。也许是因为我的英语:D。太好了,谢谢!我刚刚在gmx
    nslookup-type=srv\u提交时尝试过它。_tcp.gmx.com
    ,但它已经不起作用了。那么这是否意味着他们已经不支持它了?通常,您可以查询
    type=ns
    以首先获取权威DNS服务器并进行查询,但在您的情况下,权威的答案是相同的:<代码> NSLoop-type = NS提交。.N.GMX.UIDNS.COM< /COD>没有回答。所以,我现在可以看到这是正确的答案,但是当我已经不能为GMX工作时,我甚至不值得做C++实现吗?你同意吗?取决于你的数字。如果你有1000个客户端,其中500个在DNS中公开了配置,那么这就减轻了你一半的头痛。因为在现实世界中,500人中有250人的配置不正确,所以将其降级为四分之一。我们有很多客户交互(SIP中继、各种Web API和其他数据交换方式),他们每天都会不小心地通过他们认为无害的更改破坏这些交互。但正如我所说的,这不是一个要求,而是为方便地自动配置电子邮件客户端而提供的。最后,你得到了你所拥有的。太好了,非常感谢你!你可以让我在以后再加上C++例程,然后再检查它是否好看?
    S:220 smtp.gmail.com ESMTP ############### - gsmtp
    C:EHLO ###############
    S:250-smtp.gmail.com at your service, ###############
      250-SIZE 35882577
      250-8BITMIME
      250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH
      250-ENHANCEDSTATUSCODES
      250-PIPELINING
      250-CHUNKING
      250 SMTPUTF8
    C:QUIT
    S:221 2.0.0 closing connection ############### - gsmtp
    
    $ nslookup -type=srv _submission._tcp.gmail.com
    Server:  google-public-dns-a.google.com
    Address:  8.8.8.8
    
    Non-authoritative answer:
    _submission._tcp.gmail.com      SRV service location:
              priority       = 5
              weight         = 0
              port           = 587
              svr hostname   = smtp.gmail.com