Send email attachments from a DB with Indy


Hi

I'm using indy in a Delphi 5 development to send emails, and I want to attach PDF doc's, however the PDF docs are in a blob field in a SQL server DB.

Is there a way to stream direct from the blob field to the attachment, without having to write it to a file.

I really don't want to have to create files, I know this would be simpler in many ways, but with many users using the system it becomes more complex etc...
dealclickcoukAsked:
Who is Participating?
 
Ivanov_GConnect With a Mentor Commented:

I have suggestion with saving files
first you need to extract the blob in TADOBlobStream class and save it. Then use the procedure below.

function TfrmMain.SendMail(FileToSend: String): String;
var
  MailMsg        : TidMessage;
  MailFile       : TidAttachment;
begin
  // send the mail with the attachment
  MailMsg := TidMessage.Create(idSMTP);
  // from
  MailMsg.From.Address := 'someone@somewhere.com'; //GetOption('FromAddress');
  MailMsg.From.Name    := 'Your name'; //Application.Title;
  // to
  MailMsg.Recipients.Add;
  MailMsg.Recipients.Items[0].Address := 'receiver@domain.com'; //GetOption('ToAddress');
  MailMsg.Subject      := 'Subject';
  // the attachment
  MailFile             := TidAttachment.Create(MailMsg.MessageParts, FileToSend);
  MailFile.DisplayName := MailMsg.Subject;

  idSMTP.Connect();
  idSMTP.Send(MailMsg);

  // close connection and free memory
  idSMTP.Disconnect;
  MailFile.Free;
  MailMsg.Free;
end;
0
 
mokuleConnect With a Mentor Commented:

In addition to Ivanov_G I suggest using

GetTempFileName

 which can assure that You create unque filename
0
 
dealclickcoukAuthor Commented:

Think you're missing the point, I know I can get the blob to a file and then attach it, but I don't want to do this.

I am looking for a way to do it direct from the blob field. i.e. stream from field to attachment...
0
Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

 
Ivanov_GCommented:

   ne method LoadFromFile. The constructor itself requires filename... I don't have another idea...
0
 
kretzschmarCommented:
>I am looking for a way to do it direct from the blob field

in short, this is not possible
0
 
Lee_NoverConnect With a Mentor Commented:
a small workarround class could do it :)
try this .. not tested !


uses IdMessageCoder, IdMessage;

//MMWIN:CLASSCOPY
unit _MM_Copy_Buffer_;

interface

type
  TIdAttachmentStr = class(TIdAttachment)
  private
    FStream: TStream;
    procedure SetStream(Value: TStream);
  protected
    function MStream: TMemoryStream;
    function GetContentDisposition: string;
    procedure SetContentDisposition(const Value: string);
  public
    constructor Create(Collection: TIdMessageParts; const AStream: TStream = nil);
        reintroduce;
    destructor Destroy; override;
    procedure Encode(ADest: TStream);
    property ContentDisposition: string read GetContentDisposition write
        SetContentDisposition;
    property Stream: TStream read FStream write SetStream;
  end;


implementation

constructor TIdAttachmentStr.Create(Collection: TIdMessageParts;
  const AStream: TStream = nil);
begin
  inherited Create(Collection);
  FStream:=TMemoryStream.Create;
  Stream:=AStream;
end;

destructor TIdAttachmentStr.Destroy;
begin
  FreeAndNil(FStream);
  inherited;
end;

procedure TIdAttachmentStr.Encode(ADest: TStream);
begin
  with TIdMessageEncoderInfo(TIdMessageParts(Collection).MessageEncoderInfo).MessageEncoderClass.Create(nil) do
  try
    Encode(FStream, ADest);
  finally Free; end;
end;

function TIdAttachmentStr.GetContentDisposition: string;
begin
  Result := Headers.Values['Content-Disposition']; {do not localize}
end;

function TIdAttachmentStr.MStream: TMemoryStream;
begin
     Result:=TMemoryStream(FStream);
end;

procedure TIdAttachmentStr.SetContentDisposition(const Value: string);
begin
  Headers.Values['Content-Disposition'] := Value; {do not localize}
end;

procedure TIdAttachmentStr.SetStream(Value: TStream);
begin
     MStream.Clear;
     if Assigned(Value) then
        FStream.CopyFrom(Value, 0);
end;


end.
0
 
kretzschmarCommented:
interesting, lee :-))
0
 
Lee_NoverCommented:
bleh .. it should descend from TIdMessagePart :-) .. or .. remove the ContentDisposition property (also it's Get/Set methods) .. and Encode should have Reintroduce directive .. I think :)
0
 
dealclickcoukAuthor Commented:

Sorry to be dumb here, but I'm not that experienced with Delphi, I'm more a VB developer.

Is the above code example to be used in a new unit, or in an existing one?

Also what do I call to use it?

And just to check, is this valid Delphi 5 code?

Again sorry for the dumb questions...
0
 
Lee_NoverCommented:
seems that one slipped by ..
it's a new unit
include it in your uses clause and call smtn like:
TIdAttachmentStr.Create(msg.MessagePart, YourMemoryStream);
where YourMemoryStream is a TMemoryStream in which you've loaded the blob data
do you still need this ?
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.