2011-11-22 11 views
5

Estoy usando Delphi 2006 para crear y enviar un mensaje de correo electrónico con un archivo adjunto en una aplicación de uso personal. Envío el mensaje con una instancia de TIdSMTP y luego también coloco una copia en una carpeta IMAP específica con una instancia de TIdIMAP4. Todo esto funciona muy bien con la versión de Indy 10 que se distribuyó con BDS2006, con una excepción: el tiempo siempre es incorrecto en el encabezado del correo electrónico.Cadena de límite incorrecta en mensaje multiparte/mixto

Decidí solucionarlo si podía, y después de buscar una solución me pareció más razonable obtener la última instantánea de Indy 10 y usarla.

Eso pone la hora correcta en el encabezado del correo electrónico, pero hay un nuevo problema. ¡La cadena de límite ahora es diferente en el encabezado del mensaje que se agrega a la carpeta IMAP que el que viene en el cuerpo del correo electrónico! (Tenga en cuenta que el mensaje que se envía a través de SMTP es correcta.)

Ésta es la información de la cabecera relevante de la versión anterior de Indy 10:

Content-Type: multipart/mixed; boundary="XNlC6OyS4QSiHY2U=_jsXyps6TR34pFNsh" 
MIME-Version: 1.0 
Date: Tue, 22 Nov 2011 09:11:58 +0000 

A test of the BDS2006-bundled version of Indy 

--XNlC6OyS4QSiHY2U=_jsXyps6TR34pFNsh 
Content-Type: application/octet-stream; 
     name="20111122.xls" 

Y esta es la misma información de encabezado de Indy 10.5 0,8 (instantánea 10_4702 el que he instalado ayer):

Content-Type: multipart/mixed; boundary="CDbEncbFvL7RZdOJ3DOIRoRBs=_nBsbZms" 
MIME-Version: 1.0 
Date: Tue, 22 Nov 2011 07:33:46 -0600 

investigating more deeply, why does the boundary indicator change? 

--h=_WzGWJei29fng7SqdPpDh1nkJxJZhiGc 
Content-Type: application/octet-stream; 
    name="20111122.xls" 

el sello de tiempo es fijo, pero ahora la serie de límite es incorrecta. El resultado es que parece que no hay nada en absoluto en el mensaje que se agrega a mi carpeta IMAP.

Este es el código relevante que crea el mensaje de correo electrónico y el apego, lo envía, y pone una copia en la carpeta IMAP:

FTheMsg.Date := Now; // FTheMsg is a component dropped onto the form 
    FTheMsg.Recipients.EMailAddresses := edMailTo.Text; 
    FTheMsg.ClearBody; 
    FTheMsg.Subject := 'Glucose Readings ' + FormatDateTime('mm/dd/yy', FStartDate) + ' - ' + 
       FormatDateTime('mm/dd/yy', FEndDate); 
    FTheMsg.Body.Assign(FMemo.Lines); 

    // create the attachment 
    TIdAttachmentFile.Create(FTheMsg.MessageParts, fileName); 

    // send the mail! 
    FSmtp.Host := FSMTPHost; // values set up elsewhere, FSmtp is a component on the form 
    FImap.Host := FIMAPHost; // FImap is also a component on the form 

    FSmtp.Connect; 
    try 
    FSmtp.Send(FTheMsg); 
    FImap.Connect; 
    try 
     if (not FImap.AppendMsg('Sent Items', FTheMsg, FTheMsg.LastGeneratedHeaders, [mfSeen]))  then 
     StatusBar1.Panels[4].Text := 'Failed append msg'; 
    finally 
     FImap.Disconnect; 
    end; 
    finally 
    FSmtp.Disconnect; 
    end; 

Como ya he dicho, el correo electrónico que se envía está muy bien y se muestra correctamente . Pero el que se agrega a mi carpeta IMAP (en FImap.AppendMsg() arriba) es incorrecto. Intenté rastrear el código para ver dónde podría estar yendo mal, pero francamente, no estoy lo suficientemente familiarizado con Indy y los diversos protocolos de correo electrónico/RFC para poder determinar qué está pasando mal. Lo único que puedo decir es que la versión anterior guarda el mensaje en un archivo temporal antes de agregarlo a la carpeta, mientras que la versión más reciente lo guarda en una secuencia de memoria. Obviamente, hay algo diferente en eso, pero actualmente soy demasiado ignorante para determinar qué.

¿Hay una manera simple de corregir el problema de la marca de tiempo en la versión anterior? Si es así, estaría bien para mi uso, ya que todo lo demás parece ser correcto. Si no, ¿qué más debo hacer para solucionar el problema que se muestra aquí con la cadena de límite incorrecta?

(Como se trata de una aplicación estrictamente para mi propio uso, puedo vivir con la fecha incorrecta si tengo que hacerlo, pero no con la copia "de apariencia vacía" en mi carpeta 'Enviados'.)

Si se necesita más información, con mucho gusto le proporcionaré todo lo que pueda.

[Editar: Incorporé algo de un kludge en mi código, usando la versión anterior de Indy. Simplemente configuro la fecha/hora del mensaje a hora UTC/GMT antes de enviarlo, y eso, al menos, permite que el mensaje contenga la hora correcta al final del receptor. En particular, no me importa esa solución, pero funciona.]

Respuesta

4

No utilice la propiedad TIdMessage.Body para guardar su texto cuando hay archivos adjuntos. Ponga el texto en un objeto TIdText en su lugar. Mejor aún, use las clases TIdMessageBuilder..., como TIdMessageBuilderPlain, para preparar el cuerpo TIdMessage por usted.

Prueba esto:

FTheMsg.Clear; 
FTheMsg.Date := Now; // FTheMsg is a component dropped onto the form 
FTheMsg.Recipients.EMailAddresses := edMailTo.Text; 
FTheMsg.Subject := 'Glucose Readings ' + FormatDateTime('mm/dd/yy', FStartDate) + ' - ' + FormatDateTime('mm/dd/yy', FEndDate); 
FTheMsg.ContentType := 'multipart/mixed'; 

TIdText.Create(FTheMsg.MessageParts, FMemo.Lines).ContentType := 'text/plain'; 
TIdAttachmentFile.Create(FTheMsg.MessageParts, fileName); 

FSmtp.Connect; 
try 
    FSmtp.Send(FTheMsg); 
    FImap.Connect; 
    try 
    if (not FImap.AppendMsg('Sent Items', FTheMsg, nil, [mfSeen])) then 
     StatusBar1.Panels[4].Text := 'Failed append msg'; 
    finally 
    FImap.Disconnect; 
    end; 
finally 
    FSmtp.Disconnect; 
end; 

O:

FTheMsg.Clear; 
FTheMsg.Date := Now; // FTheMsg is a component dropped onto the form 
FTheMsg.Recipients.EMailAddresses := edMailTo.Text; 
FTheMsg.Subject := 'Glucose Readings ' + FormatDateTime('mm/dd/yy', FStartDate) + ' - ' + FormatDateTime('mm/dd/yy', FEndDate); 

with TIdMessageBuilderPlain.Create do 
try 
    PlainText.Assign(FMemo.Lines); 
    Attachments.Add(fileName); 
    FillMessage(FTheMsg); 
finally 
    Free; 
end; 

FSmtp.Connect; 
try 
    FSmtp.Send(FTheMsg); 
    FImap.Connect; 
    try 
    if (not FImap.AppendMsg('Sent Items', FTheMsg, nil, [mfSeen])) then 
     StatusBar1.Panels[4].Text := 'Failed append msg'; 
    finally 
    FImap.Disconnect; 
    end; 
finally 
    FSmtp.Disconnect; 
end; 

Ahora, dicho esto, es probable que todavía no funcionará correctamente en ambos sentidos. TIdIMAP4.AppendMsg() llama a TIdMessage.SaveToStream() internamente, lo que regenera el contenido del correo electrónico de forma reciente (y por lo tanto altera el límite utilizado en el cuerpo). Si pasa el TIdMessage.LastGeneratedHeaders preexistente o deja que TIdIMAP4.AppendMsg() tome el TIdMessage.Headers actual, no estarán sincronizados con el nuevo límite que genera TIdMessage.SaveToStream().

Para asegurarse de que SMTP e IMAP4 están sincronizados, necesitan recibir los mismos datos. Trate de llamar a TIdMessage.SaveToStream() manualmente por primera vez con la propiedad TIdMessage.NoEncode se establece en False, a continuación, establezca la propiedad TIdMessage.NoDecode en True y llamar TIdMessage.LoadFromStream() para recargar los datos guardados en que está en los TIdMessage.Headers y TIdMessage.Body propiedades, a continuación, llamar TIdSMTP.Send() y TIdIMAP4.AppendMsg() con la propiedad TIdMessage.NoEncode se establece en True por lo que TIdMessage.Headers y TIdMessage.Body se envían tal cual.

Lo sé, esto va en contra de lo que dicen TIdIMAP4.AppendMsg() comentarios/documentos a hacer. AppendMsg() actualmente no tiene en cuenta MIME, por lo que no garantiza que el límite MIME en el encabezado y el cuerpo coincidan entre sí. Trataré de verificar una solución para eso. Para Indy 11, se rediseñará todo el sistema de manejo MIME de Indy, así que me aseguraré de que sea posible preservar los límites, y/o especificar límites personalizados, para que AppendMsg() pueda combinar mejor el límite del cuerpo con el límite del encabezado.

IMAP4 es un protocolo muy complicado para trabajar en general.

+0

Bueno, eso tuvo un efecto, pero no es exactamente lo que estaba buscando. Creé una secuencia de memoria, establecí FTheMsg.NoEncode: = False, guardé el mensaje en la transmisión, reinicié FTheMsg.NoEncode: = True y recargué el mensaje, luego lo envié con TIdSMTP.Send() y TIdIMAP4.AppendMsg(), pasando NIL como el parámetro 'AdditionalHeaders'. El resultado es que no obtuve ningún archivo adjunto y ¡ningún texto visible en el mensaje! – pejurgenson

+0

Este es el mensaje completo después de que se guardó con NoEncode = False, luego se recargó con NoEncode = True 'code' Asunto: Lecturas de glucosa 11/07/11 - 20/11/11 Para: [email protected] Content-Type: multipart/mixed; boundary = "D9uTCLury1wVu8hlPEcf = _0afpyB9eNLrK" MIME-Version: 1.0 Fecha: Mar 22 Nov 2011 15:00:10 -0600 Este es un mensaje de varias partes en formato MIME . Con NoEncode = False, el mensaje guardado aparece completo. – pejurgenson

+0

lo siento, leí mal la configuración de NoEncode - ¡Lo leí como NoDecode! Oops. Si lo hago correctamente como en su nota, el mensaje llega correctamente, tanto en el destinatario como en mi carpeta 'Elementos enviados'. Muchas gracias por la ayuda, ¡es muy apreciada! Definitivamente aceptaré esta respuesta. – pejurgenson

Cuestiones relacionadas