如何正确通过IPv6发送电子邮件?

时间:2018-08-01 19:13:00

标签: ios delphi ipv6

我正在iOS和Android应用程序中开发电子邮件发送功能。

该功能是使用OpenSSL通过Gmail发送电子邮件的功能。

我正在将Delphi 10.2.3 Tokyo和Indy 10一起使用。

我将iOS应用提交到iTunes Connect,但是他们拒绝了我的应用,因为此功能在IPv6中不起作用。

他们说

  

在连接到IPv6网络的Wi-Fi上运行iOS 11.4.1的iPad和iPhone上进行检查时,我们发现您的应用程序中存在一个或多个错误。

他们还向我发送了错误说的屏幕截图

  

解析地址smtp.gmail.com时发生错误:(8)

如何解决此错误以正确使用IPv6?我的代码如下:

Procedure MailSend; 
Var
  Connected: Boolean; 
Begin 
  IdSMTP := TIdSMTP.Create(nil); 
  try 
    IdSMTP.Host     := 'smtp.gmail.com'; 
    IdSMTP.Port     := 587; 
    IdSMTP.Username := 'xxxx@gmail.com'; // UserName 
    IdSMTP.Password := 'xxxx';       // Password 
    SSL := TIdSSLIOHandlerSocketOpenSSL.Create; 

    try 
      SSL.Host := IdSMTP.Host; 
      SSL.Port := IdSMTP.Port; 
      SSL.Destination := SSL.Host + ':' + IntToStr(SSL.Port); 
      IdSMTP.IOHandler := SSL; 
      IdSMTP.UseTLS := utUseExplicitTLS; 

      IdSMTP.Socket.IPVersion := Id_IPv6; 
      try 
        IdSMTP.Connect; 
        Connected := True; 
      except 
        Connected := False; 
      end; 

      If Connected = False then 
      Begin 
        IdSMTP.Socket.IPVersion := Id_IPv4; 
        IdSMTP.Connect; 
      End; 

      Msg := TIdMessage.Create(IdSMTP); 
      try 
        Msg.OnInitializeISO           := IdMessage_InitializeISO; 
        Msg.ContentType               := 'text/plain'; 
        Msg.CharSet                   := 'UTF-8'; 
        Msg.ContentTransferEncoding   := 'BASE64'; // BASE64 (7bit) 
        //Msg.ContentTransferEncoding   := '8bit';   // RAW(8bit) 
        Msg.From.Name                 := SsNoSt; 
        Msg.From.Address              := 'xxxx@gmail.com'; 
        Msg.Recipients.EMailAddresses := 'xxxx@gmail.com'; 
        Msg.Subject                   := SsNoSt; 
        Msg.Body.Text                 := 'Unicode String (body)'; 
        IdSMTP.Send(Msg); 
      finally 
        Msg.Free; 
      end; 
      IdSMTP.Disconnect; 
    finally 
      SSL.Free; 
    end; 
  finally 
    IdSMTP.Free; 
  End; 
End; 

1 个答案:

答案 0 :(得分:4)

我发现您的SMTP代码有一些问题:

  • 您需要设置IdSMTP.IPVersion属性而不是IdSMTP.Socket.IPVersion属性。 IPVersion属性的默认值为Id_IPv4bug-不遵守ID_DEFAULT_IP_VERSION单位中的IdGlobal常数)。 Connect()Socket.IPVersion属性值覆盖IPVersion属性值,因此您实际上尝试使用Id_IPv4进行两次连接,这将在仅IPv6的网络上失败(苹果需要支持应用程序。)

  • 您没有从第二个Connect()中捕获任何错误。这可能是苹果最终看到的错误。

  • 您不应该手动设置SSL.HostSSL.PortSSL.Destination属性。让Connect()帮您解决这个问题。

尝试以下方法:

// this accessor class is needed because TIdSMTP derives from TIdTCPClientCustom
// instead of TIdTCPClient.  The IPVersion property is protected in
// TIdTCPClientCustom and not published by TIdSMTP or its ancestors.
//
// See https://github.com/IndySockets/Indy/issues/184 ...
//
type
  TIdSMTPAccess = class(TIdSMTP)
  end;

procedure MailSend; 
var
  IdSMTP: TIdSMTP;
  Msg: TIdMessage;
begin 
  IdSMTP := TIdSMTP.Create(nil);
  try
    SSL := TIdSSLIOHandlerSocketOpenSSL.Create(IdSMTP);
    IdSMTP.IOHandler := SSL;

    IdSMTP.Host     := 'smtp.gmail.com';
    IdSMTP.Port     := 587;
    IdSMTP.Username := 'xxxx@gmail.com';
    IdSMTP.Password := 'xxxx';
    IdSMTP.UseTLS := utUseExplicitTLS; 

    TIdSMTPAccess(IdSMTP).IPVersion := Id_IPv6; 
    try 
      IdSMTP.Connect; 
    except 
      TIdSMTPAccess(IdSMTP).IPVersion := Id_IPv4; 
      try
        IdSMTP.Connect; 
      except
        // unable to connect!
        Exit;
      end;
    end; 

    try
      Msg := TIdMessage.Create(nil); 
      try 
        Msg.OnInitializeISO           := IdMessage_InitializeISO; 
        Msg.ContentType               := 'text/plain'; 
        Msg.CharSet                   := 'UTF-8'; 
        Msg.ContentTransferEncoding   := 'BASE64'; // BASE64 (7bit) 
        //Msg.ContentTransferEncoding   := '8bit';   // RAW(8bit) 
        Msg.From.Name                 := SsNoSt; 
        Msg.From.Address              := 'xxxx@gmail.com'; 
        Msg.Recipients.EMailAddresses := 'xxxx@gmail.com'; 
        Msg.Subject                   := SsNoSt; 
        Msg.Body.Text                 := 'Unicode String (body)'; 

        IdSMTP.Send(Msg); 
      finally 
        Msg.Free; 
      end; 
    finally
      IdSMTP.Disconnect;
    end;
  finally 
    IdSMTP.Free; 
  end; 
end; 

或者:

type
  TIdSMTPAccess = class(TIdSMTP)
  end;

procedure MailSend; 
var
  IdSMTP: TIdSMTP;
  Msg: TIdMessage;
  Connected: Boolean;
begin 
  IdSMTP := TIdSMTP.Create(nil);
  try
    SSL := TIdSSLIOHandlerSocketOpenSSL.Create(IdSMTP);
    IdSMTP.IOHandler := SSL;

    IdSMTP.Host     := 'smtp.gmail.com';
    IdSMTP.Port     := 587;
    IdSMTP.Username := 'xxxx@gmail.com';
    IdSMTP.Password := 'xxxx';
    IdSMTP.UseTLS := utUseExplicitTLS; 

    Connected := False;

    if GStack.SupportsIPv6 then
    begin
      TIdSMTPAccess(IdSMTP).IPVersion := Id_IPv6; 
      try 
        IdSMTP.Connect; 
        Connected := True;
      except 
      end; 
    end;

    if (not Connected) and GStack.SupportsIPv4 then
    begin
      TIdSMTPAccess(IdSMTP).IPVersion := Id_IPv4; 
      try 
        IdSMTP.Connect; 
        Connected := True;
      except 
      end; 
    end;

    if not Connected then
    begin
      // unable to connect!
      Exit;
    end; 

    try
      Msg := TIdMessage.Create(nil); 
      try 
        Msg.OnInitializeISO           := IdMessage_InitializeISO; 
        Msg.ContentType               := 'text/plain'; 
        Msg.CharSet                   := 'UTF-8'; 
        Msg.ContentTransferEncoding   := 'BASE64'; // BASE64 (7bit) 
        //Msg.ContentTransferEncoding   := '8bit';   // RAW(8bit) 
        Msg.From.Name                 := SsNoSt; 
        Msg.From.Address              := 'xxxx@gmail.com'; 
        Msg.Recipients.EMailAddresses := 'xxxx@gmail.com'; 
        Msg.Subject                   := SsNoSt; 
        Msg.Body.Text                 := 'Unicode String (body)'; 

        IdSMTP.Send(Msg); 
      finally 
        Msg.Free; 
      end; 
    finally
      IdSMTP.Disconnect;
    end;
  finally 
    IdSMTP.Free; 
  end; 
end;