Re: Trying to send email with attached related and attached unrelated files

Giganews Newsgroups
Subject: Re: Trying to send email with attached related and attached unrelated files
Posted by:  Remy Lebeau (TeamB) (no.spam@no.spam.com)
Date: Wed, 10 Aug 2005

"Connie McBride" <ccoki…@iwon.com> wrote in message
news:CA856718BFD5E240ccoki…@iwon.com...

> I can get the HTML to work correctly with the embedded
> graphics. I can't seem to get the unrelated attachments to work.

You are not setting up the message properly, not even close.

> I am obviously missing something, just don't know what, yet.

I take it that you did not yet read the relavant RFCs for how MIME works,
did you?

> I have tried setting the parent part of the attachments to 0, 1,
> etc.  Every time I set it, I get a list index out of bounds(0).

As well you should be, because you are not using the ParentPart correctly.
In fact, the code you showed is not making any use of the ParentPart at all,
which means your MessageParts hierarchy is completely malformed.

> If I set it to -1, then the html no longer works.

That is because your code is not correct to begin with.

>    if lbAttach.Items.Count > 0 then //contains a list of optional
> attachments
>      emMessage.ContentType := 'multipart/alternative'
>    else
>      emMessage.ContentType := 'multipart/related';

That is wrong.  You should be using 'multipart/mixed' instead.

>      if reBody.Lines.Count > 0 then
>      begin
>          slist.Insert(0, reBody.Text);
>          with TIdText.Create(emMessage.MessageParts, sList) do
>            ContentType:='text/html';
>      end;
>      with TIdText.Create(emMessage.MessageParts, sList) do
>            ContentType:='multipart/related';
>      CreateAttachment(fName)

That is wrong.  You need to place both the HTML and the PDF inside the
'multipart/related' part, not outside of it.

>      with TIdText.Create(emMessage.MessageParts, sList) do
>          ContentType:='text/html';
>
>      with TIdText.Create(emMessage.MessageParts, nil) do
>          ContentType:='multipart/related';

Again, you are completely mis-managing the order of the MessageParts and
their ContentType values.

> //This is where the problem is.

Your code has a lot of problems.

>      with TIdText.Create(emMessage.MessageParts, nil) do
>        ContentType:='text/plain';
>
>      with TIdText.Create(emMessage.MessageParts, nil) do
>        ContentType:='multipart/mixed';

And once again, you are still not managing the MessageParts correctly.

With all of that said, you code is creating a message that contains only a
single level hierarchy of MessageParts items regardless of which items you
actually add.  To do what you are asking for, you need to set up one of many
possible multi-level hierarchies instead, depending on what you actually
want to include in the message.

Try the following code instead (untested):

    procedure TdlgEmail.EmailMessage;
    var
        x, ParentIdx : Integer;
        SearchRec : TSearchRec;
        sRelatedFiles: TStrings;
        fName: String;

        procedure LoadHTMLContent(ADest: TStrings);
        var
            sHTML: TStrings;
        begin
            ADest.Assign(reBody.Lines);
            if not PDFFormat and FileExists(fName) then
            begin
                sHTML := TStringList.Create;
                try
                    sHTML.LoadFromFile(fName);
                    ADest.AddStrings(sHTML);
                finally
                    FreeAndNil(sHTML);
                end;
            end;
        end;

    begin
        // initialize addresses, SMTP settings, etc...

        if PDFFormat then
            fName := UserFPath + 'rpt001.pdf'
        else
            fName := UserFPath + 'rpt001.htm';

        sRelatedFiles := TStringList.Create;
        try
            if PDFFormat and FileExists(fName) then
            begin
                sRelatedFiles.Add(fName);
            end
            else
            begin
                if FindFirst(UserFPath + 'rpt*.jpg', faAnyFile and not
faDirectory, SearchRec) = 0 then
                try
                    repeat
                        sRelatedFiles.Add(UserFPath + SearchRec.Name);
                    until FindNext(SearchRec) <> 0;
                finally
                    FindClose(SearchRec);
                end;
            end;

            if (lbAttach.Items.Count > 0) and (sRelatedFiles.Count > 0) then
            begin
                with TIdText.Create(emMessage.MessageParts, nil) do
                    ContentType := 'multipart/related; type="text/html"';
                ParentIdx := 0;
            end
            else
            begin
                ParentIdx := -1;
            end;

            if (lbAttach.Items.Count > 0) or (sRelatedFiles.Count > 0) then
            begin
                with TIdText.Create(emMessage.MessageParts, nil) do
                begin
                    ContentType := 'text/html';
                    ParentPart := idx;
                    LoadHTMLContent(Body);
                end
                else
                begin
                    LoadHTMLContent(emMessage.Body);
                end;
            end;

            for x := 0 to sRelatedFiles.Count - 1 do
                CreateAttachment(sRelatedFiles[x], ParentIdx);

            if lbAttach.Items.Count > 0 then
            begin
                for x := 0 to lbAttach.Items.Count - 1 do
                    CreateAttachment(lbAttach.Items[x]);
                emMessage.ContentType := 'multipart/mixed';
            end
            else
            begin
                if sRelatedFiles.Count > 0 then
                    emMessage.ContentType := 'multipart/related;
type="text/html"'
                else
                    emMessage.ContentType := 'text/html';
            end;
        finally
            FreeAndNil(sRelatedFiles);
        end;

        doMail;

        // clean up stuff...
    end;

    procedure tdlgEMail.CreateAttachment(const AFileName : String;
AParentPart : Integer = -1);
    var
        s: String;
    begin
        s := ExtractFileName(AFileName);
        with TIdAttachmentFile.Create(emMessage.MessageParts, AFileName) do
        begin
            ContentID := s;
            ContentType := GetMIMETypeFromFile(AFileName);
            Filename := s;
            ParentPart := AParentPart;
        end;
    end;

    function TdlgEmail.DoMail(Disconnect : Boolean = True): Boolean;
    begin
        Result := False;
        try
            if not SMTP.Connected then
                SMTP.Connect;

            SMTP.Send(emMessage);
            Result := True;
        except
            on E:Exception do
            begin
                MessageDlg('There has been an error sending mail.' + #13 +
'Please establish an internet connection and verify all'+ #13 + 'email
addresses before trying again.' + #13 + #13 + E.Message, mtError,
[mbOK,mbCancel], 0);
            end;
        end;
        Screen.Cursor := crDefault;
        if SMTP.Connected and Disconnect then
            SMTP.Disconnect;
    end;

Gambit

Replies

In response to

Trying to send email with attached related and attached unrelated files posted by Connie McBride on Tue, 9 Aug 2005