2011-11-22 12 views
5

Utilizzo Delphi 2006 per creare e inviare un messaggio di posta elettronica con un allegato in un'applicazione per uso personale. Invio il messaggio con un'istanza di TIdSMTP e quindi inserisco una copia in una cartella IMAP specifica con un'istanza di TIdIMAP4. Tutto questo funziona molto bene con la versione di Indy 10 che è stata distribuita con BDS2006, con un'eccezione: il tempo è sempre errato nell'intestazione dell'e-mail.Stringa limite non corretta nel messaggio multipart/mixed

Ho deciso di risolvere il problema se potessi, e dopo aver cercato una soluzione mi è sembrato più ragionevole ottenere l'ultima istantanea di Indy 10 e usarla.

Che inserisce l'ora corretta nell'intestazione dell'e-mail, ma c'è un nuovo problema. La stringa limite ora è diversa nell'intestazione del messaggio che viene aggiunta alla cartella IMAP rispetto a ciò che arriva nel corpo dell'e-mail! (Si prega di notare che il messaggio che è stato inviato tramite SMTP è corretta.)

Queste sono le informazioni di intestazione rilevanti dalla versione precedente di 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" 

E questa è la stessa informazione colpo di testa da Indy 10.5 0,8 (snapshot 10_4702 che ho installato ieri):

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" 

il timestamp è fisso, ma ora la stringa di confine non è corretto. Il risultato è che sembra non esserci nulla nel messaggio che viene aggiunto alla mia cartella IMAP.

Ecco il relativo codice che crea il messaggio e-mail e allegati, invia, e mette una copia nella cartella 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; 

Come ho detto, l'e-mail che viene inviato è fine e visualizza correttamente . Ma quello che viene aggiunto alla mia cartella IMAP (in FImap.AppendMsg() sopra) non è corretto. Ho tentato di rintracciare il codice per vedere dove avrebbe potuto andare storto, ma francamente, non sono abbastanza familiare con Indy e con i vari protocolli e RFC per poter determinare cosa sta andando storto. Tutto quello che posso dire è che la versione precedente salva il messaggio in un file temporaneo prima di aggiungerlo alla cartella, mentre la versione più recente lo salva invece in un flusso di memoria. Ovviamente, qualcosa è diverso a riguardo, ma al momento sono troppo ignorante per determinare cosa.

C'è un modo semplice per correggere il problema di timestamp nella vecchia versione? Se è così, sarebbe perfetto per il mio uso, dato che tutto il resto sembra essere corretto. In caso contrario, cos'altro devo fare per risolvere il problema esposto qui con la stringa di confine errata?

(Poiché si tratta di un'applicazione esclusivamente per mio uso personale, posso vivere con la data corretta se devo, ma non con la copia di "vuoto-apparire" nella cartella 'Posta inviata'.)

Se sono necessarie ulteriori informazioni, fornirò volentieri tutto ciò che posso.

[Modifica: ho incorporato qualcosa di un kludge nel mio codice, utilizzando la versione precedente di Indy. Ho semplicemente impostato la data/ora del messaggio sull'ora UTC/GMT prima di inviarlo e, almeno, consente al messaggio di contenere l'ora corretta alla fine del destinatario. Non mi interessa particolarmente quella correzione, ma funziona.]

risposta

4

Non utilizzare la proprietà TIdMessage.Body per conservare il testo quando è presente un allegato. Inserisci invece il testo in un oggetto TIdText. Ancora meglio, utilizzare le classi TIdMessageBuilder..., ad esempio TIdMessageBuilderPlain, per preparare il corpo TIdMessage.

Prova questo:

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; 

Oppure:

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; 

Ora, detto questo, è probabile che sarà ancora non funzionare correttamente in entrambi i casi. TIdIMAP4.AppendMsg() chiama internamente il numero TIdMessage.SaveToStream(), che rigenera il contenuto dell'email (e quindi modifica il limite utilizzato nel corpo). Sia che si passa nel pre-esistente TIdMessage.LastGeneratedHeaders o lasciare TIdIMAP4.AppendMsg() afferrare la corrente TIdMessage.Headers, saranno fuori sincrono con il nuovo confine che TIdMessage.SaveToStream() genera.

Per assicurarsi sia SMTP e IMAP4 sono in sincronia, hanno bisogno di ricevere gli stessi dati. Prova a chiamare TIdMessage.SaveToStream() manualmente prima con la TIdMessage.NoEncode proprietà impostata su False, quindi impostare la proprietà TIdMessage.NoDecode True e chiamare TIdMessage.LoadFromStream() ricaricare i dati salvati come-è nelle proprietà TIdMessage.Headers e TIdMessage.Body, quindi chiamare TIdSMTP.Send() e TIdIMAP4.AppendMsg() con la TIdMessage.NoEncode proprietà impostata su True quindi TIdMessage.Headers e TIdMessage.Body vengono inviati così come sono.

lo so, questo va contro quello che i commenti TIdIMAP4.AppendMsg()/docs dicono di fare. AppendMsg() attualmente non prende in considerazione MIME, quindi non garantisce che il limite MIME nell'intestazione e il corpo corrispondano l'un l'altro. Proverò a controllare una correzione per quello. Per Indy 11, l'intero sistema di gestione MIME di Indy verrà ridisegnato, quindi mi assicurerò che sia possibile conservare i limiti e/o specificare i limiti personalizzati, quindi AppendMsg() può abbinare meglio il limite del corpo al limite dell'intestazione.

IMAP4 è un protocollo molto difficile con cui lavorare in generale.

+0

Beh, questo ha avuto un effetto, ma non esattamente quello che stavo cercando. Ho creato un flusso di memoria, impostato FTheMsg.NoEncode: = False, salvato il messaggio nello stream, reimpostato FTheMsg.NoEncode: = True e ricaricato il messaggio, quindi inviato con TIdSMTP.Send() e TIdIMAP4.AppendMsg(), passando NIL come parametro "AdditionalHeaders". Il risultato è che non ho alcun allegato e nessun testo visibile nel messaggio! – pejurgenson

+0

Questo è il messaggio completo dopo che è stato salvato con NoEncode = False, quindi ricaricato con NoEncode = True 'code' Subject: Glucose Readings 11/07/11 - 11/2/11/11 A: [email protected] Content-Type: multipart/mixed; boundary = "D9uTCLury1wVu8hlPEcf = _0afpyB9eNLrK" MIME-Version: 1.0 Data: Tue, 22 Nov 2011 15:00:10 -0600 Questo è un messaggio in più parti nel formato MIME . Con NoEncode = False, il messaggio salvato appare completo. – pejurgenson

+0

scusa, ho letto male il bit sull'impostazione di NoEncode - l'ho letto come NoDecode! Ops. Se lo faccio correttamente come nella nota, il messaggio arriva correttamente, sia nel destinatario che nella cartella "Posta inviata". Grazie mille per l'aiuto, è molto apprezzato! Accetterò sicuramente questa risposta. – pejurgenson

Problemi correlati