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

mir*_*iro 3 delphi ipv6 ios

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

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

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

我向 iTunes Connect 提交了我的 iOS 应用程序,但他们拒绝了我的应用程序,因为此功能在 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; 
Run Code Online (Sandbox Code Playgroud)

Rem*_*eau 5

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

  • 您需要设置IdSMTP.IPVersion属性而不是IdSMTP.Socket.IPVersion属性。该IPVersion属性的默认值是Id_IPv4错误- 它不尊重单位ID_DEFAULT_IP_VERSION中的常量IdGlobal)。 Connect()使用Socket.IPVersion属性值覆盖属性值IPVersion,因此您实际上尝试使用Id_IPv4两次进行连接,这在纯 IPv6 网络上会失败(Apple 需要应用程序支持)。

  • 从第二个开始你没有发现任何错误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; 
Run Code Online (Sandbox Code Playgroud)

或者:

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;
Run Code Online (Sandbox Code Playgroud)