【问题标题】:Poco unable to send emailPoco 无法发送电子邮件
【发布时间】:2015-03-27 14:05:29
【问题描述】:

我正在尝试使用 Poco 库发送电子邮件。平台是 OS XYosemite 10.10.2 我使用的是 Qt 5.3 32 位。我遵循here 的官方说明,由于我使用的是 32 位 Qt,并且希望库是静态链接的,所以我使用了

./configure --omit=Data/ODBC,Data/MySQL --config=Darwin32

(我不需要 MySQL/ODBC 模块)。它正确安装在/usr/local 中,然后我链接了必要的动态库(PocoNetPocoFoundation 以及其他10 个库),并尝试了以下代码,我找到了here。我要做的是从我的帐户本身向我的 gmail 帐户发送一封电子邮件:

#include "MailSender.hpp"

#include <Poco/Net/MailMessage.h>
#include <Poco/Net/MailRecipient.h>
#include <Poco/Net/SMTPClientSession.h>
#include <Poco/Net/NetException.h>
#include <Poco/Net/SecureSMTPClientSession.h>
#include <Poco/Net/InvalidCertificateHandler.h>
#include <Poco/Net/AcceptCertificateHandler.h>
#include <Poco/Net/SSLManager.h>
#include <Poco/Net/SecureStreamSocket.h>
#include <Poco/Net/MailRecipient.h>

#include <iostream>
#include <QDebug>

using Poco::Net::InvalidCertificateHandler;
using Poco::Net::AcceptCertificateHandler;
using Poco::Net::Context;
using Poco::Net::SSLManager;
using Poco::Net::SecureStreamSocket;
using Poco::Net::SocketAddress;
using Poco::Net::SecureSMTPClientSession;
using Poco::Net::SMTPClientSession;
using Poco::SharedPtr;
using Poco::Net::MailMessage;
using Poco::Net::MailRecipient;
using namespace std;

MailSender::MailSender()
{
SharedPtr<InvalidCertificateHandler> pCert = new AcceptCertificateHandler(false);

string host = "smtp.gmail.com";
int port = 25;

Context::Ptr pContext = new Poco::Net::Context(Context::CLIENT_USE, "", "", "", Context::VERIFY_NONE, 9, false, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
SSLManager::instance().initializeClient(0, pCert, pContext);

Poco::Net::SecureSMTPClientSession* pSecure = new Poco::Net::SecureSMTPClientSession(host, port);
Poco::Net::SecureSMTPClientSession* pSession_ = new Poco::Net::SecureSMTPClientSession(host, port);

SecureStreamSocket* pSSLSocket = new SecureStreamSocket(pContext);
pSSLSocket->connect(SocketAddress(host, port));
pSecure = new SecureSMTPClientSession(*pSSLSocket);
pSession_ = pSecure;
pSecure->login();
if (!pSecure->startTLS(pContext))
   throw std::string("Failed to start TLS connection.");

std::string sUserName = "my_email_id";
std::string sPassword = "my_password";

pSession_->login(SMTPClientSession::AUTH_LOGIN, sUserName, sPassword);


string to = "my_email_id";
string from = "my_email_id";
string subject = "Your first e-mail message sent using Poco Libraries";
subject = MailMessage::encodeWord(subject, "UTF-8");
string content = "Well done! You've successfully sent your first message using Poco SMTPClientSession";
MailMessage message;
message.setSender(from);
message.addRecipient(MailRecipient(MailRecipient::PRIMARY_RECIPIENT, to));
message.setSubject(subject);
message.setContentType("text/plain; charset=UTF-8");
message.setContent(content, MailMessage::ENCODING_8BIT);



try {
    pSession_->sendMessage(message);
    pSession_->close();
} catch (Poco::Net::SMTPException &e) {
    qDebug() << e.displayText().c_str() << endl;
}
catch (Poco::Net::NetException &e) {
    qDebug() << e.displayText().c_str() << endl;
}

}

当我运行它时,我收到以下错误:

libc++abi.dylib:在 Qt 控制台中以 Poco::Net::SSLException: SSL Exception 类型的未捕获异常终止。

Apple 生成的故障转储显示:

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib          0x9b7f369a __pthread_kill + 10
1   libsystem_pthread.dylib         0x90a04f19 pthread_kill + 101
2   libsystem_c.dylib               0x96861eee abort + 156
3   libc++abi.dylib                 0x965782f9 abort_message + 169
4   libc++abi.dylib                 0x9659b483 default_terminate_handler() + 272
5   libc++abi.dylib                 0x96598ac0 std::__terminate(void (*)()) + 14
6   libc++abi.dylib                 0x965986ee __cxa_rethrow + 103
7   libPocoNetSSL.30.dylib          0x02c253ff Poco::Net::SecureSocketImpl::connectSSL(bool) + 943
8   libPocoNetSSL.30.dylib          0x02c24fee Poco::Net::SecureSocketImpl::connect(Poco::Net::SocketAddress const&, bool) + 94
9   libPocoNetSSL.30.dylib          0x02c28a61 Poco::Net::SecureStreamSocketImpl::connect(Poco::Net::SocketAddress const&) + 49
10  libPocoNet.30.dylib             0x02b1368b Poco::Net::StreamSocket::connect(Poco::Net::SocketAddress const&) + 27

不知何故,代码在pSSLSocket-&gt;connect(SocketAddress(host, port));失败

我已经链接了PocoNetPocoNetSSLPocoFoundation等,一共生成了12个动态库。

知道如何解决这个问题吗?

【问题讨论】:

  • 我认为 gmail 服务器不接受纯文本登录,因此您可能想尝试使用 SecureSMTPClientSession 而不是 SMTPClientSession。我也不确定smtp.gmail.comHELO 中告诉它你是smtp.gmail.com 会有多高兴。
  • 这是另一个问题,好像在某处有一个SecureSMTPClientSession 模块,因为我整天都在谷歌搜索,但我在任何地方都没有看到它。至少不在Poco/Net 中。 ??????
  • 它是NetSSL_OpenSSL 库的一部分,位于Poco/Net/SecureSMTPClientSession.h,如the documentation 所述。
  • 这就是我所说的,我的Net文件夹中没有名为SecureSMTPClientSession.h的文件..
  • 您只安装了NetFoundation。你还需要NetSSL_OpenSSL

标签: c++ qt smtp osx-yosemite poco-libraries


【解决方案1】:

对于构建,在静态构建配置中构建 NetSSL 示例时存在错误(不是关键,但 OP 不知道如何解决它),请参阅已解决的 GitHub issue

要发送电子邮件,请参阅 Poco 论坛上的SecureSMTPClientSession with GMail and SSL

using Poco::Net::InvalidCertificateHandler;
using Poco::Net::AcceptCertificateHandler;
using Poco::Net::Context;
using Poco::Net::SSLManager;
using Poco::Net::SecureStreamSocket;
using Poco::Net::SocketAddress;
using Poco::Net::SecureSMTPClientSession;
using Poco::Net::SMTPClientSession;
using Poco::SharedPtr;

SharedPtr<InvalidCertificateHandler> pCert = new AcceptCertificateHandler(false);
Context::Ptr pContext = new Poco::Net::Context(Context::CLIENT_USE, "", "", "", Context::VERIFY_NONE, 9, false, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
SSLManager::instance().initializeClient(0, pCert, pContext);

SecureStreamSocket* pSSLSocket = new SecureStreamSocket(pContext);
pSSLSocket->connect(SocketAddress(sSmtpServer, nSmtpPort));
pSecure = new SecureSMTPClientSession(*pSSLSocket);
pSession_ = pSecure;
pSecure->login();
if (!pSecure->startTLS(pContext))
   throw std::string("Failed to start TLS connection.");

pSession_->login(SMTPClientSession::AUTH_LOGIN, sUserName, sPassword);
pSession_->sendMessage(*pSelectedMailMessage_);
pSession_->close();

另见 NetSSL Mail example:

SharedPtr<InvalidCertificateHandler> pCert = new ConsoleCertificateHandler(false); // ask the user via console
Context::Ptr pContext = new Context(Context::CLIENT_USE, "", "", "", Context::VERIFY_RELAXED, 9, true, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
SSLManager::instance().initializeClient(0, pCert, pContext);

MailMessage message;
message.setSender(sender);
message.addRecipient(MailRecipient(MailRecipient::PRIMARY_RECIPIENT, recipient));
message.setSubject("Hello from the POCO C++ Libraries");
std::string content;
content += "Hello ";
content += recipient;
content += ",\r\n\r\n";
content += "This is a greeting from the POCO C++ Libraries.\r\n\r\n";
std::string logo(reinterpret_cast<const char*>(PocoLogo), sizeof(PocoLogo));
message.addContent(new StringPartSource(content));
message.addAttachment("logo", new StringPartSource(logo, "image/gif"));

SecureSMTPClientSession session(mailhost);
session.login();
session.startTLS(pContext);
if (!username.empty())
{
    session.login(SMTPClientSession::AUTH_LOGIN, username, password);
}
session.sendMessage(message);
session.close();

【讨论】:

  • 感谢您的回答。但是此代码再次显示链接器错误,请参阅我的问题的编辑..
  • 您要么没有为 i386 构建,要么正在链接一些陈旧的二进制文件。确保您的构建树中有 i386/libPoco* 二进制文件,并且确实与这些文件链接
  • 嗯,我在configure 步骤中明确提到了config=Darwin32。我还有什么需要做的吗?
  • 在这个例子中,libPocoNetlibPocoFoundation 不足以进行链接吗?我需要安装到我的/usr/local/ 中的所有libPoco* 库吗???
  • 不,它们还不够,你需要 libPocoNetSSL,这已经说过了。只要您的链接器可以找到它们并且它们适用于正确的平台,您的二进制文件在哪里并不重要。
猜你喜欢
  • 2013-09-22
  • 2011-02-18
  • 1970-01-01
  • 2019-01-19
  • 2013-06-07
  • 2016-12-16
  • 2013-04-08
  • 2012-12-05
相关资源
最近更新 更多