2016-03-04 2 views
4

Я пытаюсь прикрепить PDF-документ к электронному письму с помощью Delphi (D10S), и я хотел бы установить имя для чего-то другого, кроме имени файла в файловой системе.Настройка имени вложения электронной почты с помощью TIdMessageBuilderHtml

Я нашел следующую нить (с 2011 года), где Реми Лебо утверждает, что вы можете добиться этого, установив Name свойство TIdMessageBuilderAttachment объекта при подключении их к электронной почте с помощью TIdMessageBuilderHtml:

How to name attachment files constructed by TIdMessageBuilderHtml

Однако, как это ни звучит, это не работает для меня. Письмо приходит, но приложение поставляется с исходным именем файла, а не тем, которое я указал.

Ниже приведен фрагмент кода, который я ожидаю делать, как я описал, но по какой-либо причине этого не делает. В этом случае я хотел бы, чтобы имя файла получилось как desired_filename.pdf, но оно проходит через undesired_filename.pdf. Я удалил учетные данные почтового сервера по очевидным причинам:

procedure TForm4.Button1Click(Sender: TObject); 
var 
    FMessageBuilder : TIdMessageBuilderHtml; 
    FSMTP : TIdSMTP; 
    FMessage : TIdMessage; 
    FAttachment : TIdMessageBuilderAttachment; 
begin 
    FMessage := TIdMessage.Create(); 
    FMessageBuilder := TIdMessageBuilderHtml.Create; 
    FSMTP := TIdSMTP.Create; 

    FAttachment := FMessageBuilder.Attachments.Add('c:\undesired_filename.pdf'); 
    FAttachment.Name := 'desired_filename.pdf'; 
    FMessageBuilder.FillMessage(FMessage); 

    FMessage.Sender.Address := '<Insert Sender Address>'; 
    FMessage.Sender.Name := '<Insert Sender Name>'; 
    FMessage.From.Address := '<Insert From Address>'; 
    FMessage.From.Name := '<Insert From Name>'; 
    FMessage.Recipients.EMailAddresses := '<Insert Recepient Address>'; 
    FMessage.Subject := 'Attachment Test'; 

    FSMTP.Host := '<Insert Mail Host>'; 
    FSMTP.Username := '<Insert Username>'; 
    FSMTP.Password := '<Insert Password>'; 
    FSMTP.Connect; 
    FSMTP.Send(FMessage); 
    FSMTP.Disconnect; 
end; 

Я испытал это в D10S и ХЕ и оба делают то же самое. Любые идеи, что я делаю неправильно?

ответ

3

TIdMessageBuilderAttachment имеет как FileName и Name свойствами. При добавлении вложения к строителю эти значения присваиваются соответствующим свойствам объекта TIdAttachment, который добавляется в коллекцию TIdMessage.MessageParts.

Если вложение имеет Name назначенное значение помещается в атрибуте заголовка Content-Typename, например:

Content-Type: media/type; name="desired_filename.pdf" 

Если вложение имеет FileName назначенное значение помещаются в атрибуте filename из Content-Disposition заголовка, например:

Content-Disposition: attachment; filename="undesired_filename.pdf" 

Если оба заголовки присутствуют, соответствующие читатели дают Content-Disposition приоритет при ища имя файла. Вот почему ваш читатель отображает нежелательное имя файла.

При добавлении физического файла в конструктор TIdMessageBuilderAttachment в настоящее время не позволяет указать другой файл FileName, отличный от реального. Это связано с тем, что TIdMessageBuilderAttachment не тот, кто действительно загружает файл. Он просто создает новый объект TIdAttachmentFile и присваивает его FileName этому объекту, поэтому ему требуется подлинное имя файла, иначе вложение не будет загружаться при отправке электронной почты. Тем не менее, TIdAttachmentFile позволяет настраивать свой собственный FileName после создания. Он имеет отдельное свойство StoredPathName, чтобы отслеживать физический файл, поэтому его FileName может быть тем, чем вы хотите.

В примере @ fantaghirocco, добавив в TStream к застройщику вызывает TIdAttachmentMemory быть добавлены к TIdMessage вместо TIdAttachmentFile. Поскольку физический файл не задействован, вложений может быть любым, что вы хотите.

Итак, TIdMessageBuilderAttachment необходимо будет обновить, чтобы установить физическое прикрепление файла FileName отдельно от его StoredPathName. В то же время, вы можете вручную обновить TIdAttachmentFile.FileName свойство после TIdMessage заполнена, например:

FAttachment := FMessageBuilder.Attachments.Add('c:\undesired_filename.pdf'); 
FAttachment.Name := 'desired_filename.pdf'; 
FMessageBuilder.FillMessage(FMessage); 

for I := 0 to FMessage.MessageParts.Count-1 do 
begin 
    if FMessage.MessageParts[I].PartType = mptAttachment then 
    FMessage.MessageParts[I].FileName = FMessage.MessageParts[I].Name; 
end; 
+1

upvoted: никогда не возиться с этим парнем! – fantaghirocco

+0

Ничего себе, я никогда не ожидал, что ты придешь и ответишь на это! Благодаря! Если установка свойства «name» в «TIdMessageBuilderAttachment» обновляет заголовок «Content-Type», но «Content-Disposition» (заполненное «FileName») имеет приоритет, означает ли это, что пример, который вы дали в связанном с ним потоке есть эта же проблема, или есть какая-то тонкая разница, которую я пропустил? Я просто предположил, что работал так, как будто он был доволен вашим ответом. –

+2

Более ранний пример будет страдать от одной и той же проблемы. Это ограничение «TIdMessageBuilder», которое я не учитывал при первом написании, поэтому мне придется сделать для него обновление, чтобы учесть это, возможно, с новым свойством. –

5

Использование TIdMessageBuilderAttachments.Add перегрузки, который принимает TStream и установив TIdMessageBuilderAttachment.FileName свойство нужное имя делает трюк для меня на xe4, Инди 10.6.0.4975.

stream := TFileStream.Create('c:\undesired_filename.pdf', fmOpenRead); 
FAttachment := FMessageBuilder.Attachments.Add(stream, 'application/pdf'); 
FAttachment.FileName := 'desired_filename.pdf'; 
+1

Это работает, спасибо! Однако мне все еще немного интересно узнать, что было не так с методом, который я использовал. Я подожду, чтобы увидеть, сможет ли кто-нибудь еще понять это, прежде чем я пометию это как ответ (у меня также нет достаточной репутации для +1, но я бы, если бы мог). –

+1

@Adam приветствую вас, рассмотрите это как обходное решение, пока '@Remy не решит вашу проблему. – fantaghirocco

+2

Одна из проблем с этим подходом заключается в том, что эта перегрузка заставляет данные ввода' TStream' копироваться в память (объект 'TIdAttachmentMemory' добавлен в коллекцию 'TIdMessage.MessageParts'), поэтому это не рекомендуется для больших вложений. –

 Смежные вопросы

  • Нет связанных вопросов^_^