Jump to content
Mark Williams

Byte Array to String

Recommended Posts

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

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,...).

  • Thanks 1

Share this post


Link to post
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;

 

  • Thanks 1

Share this post


Link to post
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

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×