Mark Williams 14 Posted November 26, 2020 Outlook's MailItem gives access to the RTFBody property for RTF formatted emails. This is described in the MS docs Quote Returns or sets a Byte array that represents the body of the Microsoft Outlook item in Rich Text Format. I need to get the RTFBody as a string that I can then write to file. I can't work out how to do this in Delphi 10.4. If found the following example from a post 8 years ago: System.Text.Encoding.UTF8.GetString(mailItem.RTFBody); This doesn't compile in 10.4. Can anyone please advise what function should be used with 10.4? Share this post Link to post
David Heffernan 2345 Posted November 26, 2020 If it's a byte array, why don't you just write that to file? Why do you need to convert it to a string variable? 2 Share this post Link to post
FPiette 383 Posted November 27, 2020 RTFBody is an array of byte, each byte is an ASCII character, the last one being #0. You can consider this as being a C string type. To save it to a file, you can write: procedure TForm1.Button1Click(Sender: TObject); var ANameSpace : Variant; AFolderItem : Variant; AMailItem : Variant; RTFBody : array of Byte; Stream : TFileStream; begin OutlookApplication1.Connect; ANameSpace := OutlookApplication1.GetNameSpace('MAPI'); AFolderItem := ANameSpace.GetDefaultFolder(olFolderInbox); AMailItem := AFolderItem.Items(1); RTFBody := AMailItem.RTFBody; Stream := TFileStream.Create('RTFBody.rtf', fmCreate); try Stream.Write(RTFBody[0], Length(RTFBody)); finally Stream.Free; end; end; If you want to convert to a string here is a possibility: Get it into an AnsiString using SetString. Convert the AnsiString to String (Unicode). Now you can handle it as any other string. Here is some example code to display the first email body in a TMemo: procedure TForm1.Button1Click(Sender: TObject); var ANameSpace : Variant; AFolderItem : Variant; AMailItem : Variant; RTFBody : array of Byte; RTFAnsiString : AnsiString; RTFString : String; begin OutlookApplication1.Connect; ANameSpace := OutlookApplication1.GetNameSpace('MAPI'); AFolderItem := ANameSpace.GetDefaultFolder(olFolderInbox); AMailItem := AFolderItem.Items(1); RTFBody := AMailItem.RTFBody; SetString(RTFAnsiString, PAnsiChar(@RTFBody[0]), Length(RTFBody)); RTFString := String(RTFAnsiString); Memo1.Lines.Add(RtfString); end; Don't forget to add error checking in the code (No Outlook, no mail, empty mail,...). 1 Share this post Link to post
Remy Lebeau 1396 Posted November 28, 2020 17 hours ago, FPiette said: If you want to convert to a string here is a possibility: Get it into an AnsiString using SetString. Convert the AnsiString to String (Unicode). Now you can handle it as any other string. Better to use SysUtils.TEncoding.GetString(), then no intermediate AnsiString is needed. procedure TForm1.Button1Click(Sender: TObject); var ANameSpace : Variant; AFolderItem : Variant; AMailItem : Variant; RTFBody : array of Byte; RTFString : String; begin OutlookApplication1.Connect; ANameSpace := OutlookApplication1.GetNameSpace('MAPI'); AFolderItem := ANameSpace.GetDefaultFolder(olFolderInbox); AMailItem := AFolderItem.Items(1); RTFBody := AMailItem.RTFBody; RTFString := TEncoding.Default.GetString(RTFBody); Memo1.Lines.Add(RtfString); end; 1 Share this post Link to post
FPiette 383 Posted December 1, 2020 On 11/28/2020 at 2:10 AM, Remy Lebeau said: Better to use SysUtils.TEncoding.GetString(), then no intermediate AnsiString is needed. The OP is likely to need the AnsiString. That why I showed how to do that. Share this post Link to post
FPiette 383 Posted December 1, 2020 I made another version which doesn't use any variant (Late binding) and has the advantage that during code editing, you get Delphi Code Insight showing all the methods and properties. unit OutlookDemo; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.OleServer, // To get TOutlookApplication version 2010, you need to install the // component package dcloffice2010XYZ.bpl (XYZ being Delphi version, // 260 for D10.3, 270 for D10.4). This package is in Embarcadero Studio bin // directory. Outlook2010; type TOutlookDemoMainForm = class(TForm) OutlookApplication1: TOutlookApplication; RTFBodyButton: TButton; Memo1: TMemo; procedure RTFBodyButtonClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var OutlookDemoMainForm: TOutlookDemoMainForm; implementation {$R *.dfm} procedure TOutlookDemoMainForm.RTFBodyButtonClick(Sender: TObject); var ANameSpace : NameSpace; AFolderItem : MAPIFolder; AMailItem : MailItem; RTFBody : array of Byte; RTFString : String; Stream : TFileStream; begin OutlookApplication1.Connect; ANameSpace := OutlookApplication1.GetNameSpace('MAPI'); AFolderItem := ANameSpace.GetDefaultFolder(olFolderInbox); AMailItem := AFolderItem.Items.Item(1) as MailItem; RTFBody := AMailItem.RTFBody; RTFString := TEncoding.Default.GetString(RTFBody); Memo1.Lines.Add(RTFString); Stream := TFileStream.Create('RTFBody.rtf', fmCreate); try Stream.Write(RTFBody[0], Length(RTFBody)); finally Stream.Free; end; end; end. Share this post Link to post