glasswalk3r has asked for the wisdom of the Perl Monks concerning the following question:

Greetings fellow monks,

I'm trying to use Redemption with ActivePerl by using the Win32::OLE module.

While I'm being able to send emails directly, I really lost about how to setup an extra RFC822 header. I believe that I'm missing something simple, probably a little concept that I'm not understanding well.

I can send emails with extra header easily by using VBA with this code below:

Sub createEmail() Dim olApp As Outlook.Application Set olApp = New Outlook.Application Dim olMail As MailItem Set olMail = Outlook.CreateItem(olMailItem) With olMail .To = "glasswalk3r@yahoo.com.br" .Subject = "Testing a customized header" .BodyFormat = olFormatPlain .body = "Hello there!" & vbCrLf _ & "This is a VBA POC (with Redemption!) generated email an +d should have a " _ & "nice customized header (X-Reported-Via)." & vbCrLf _ & "My best regards," & vbCrLf & "Alceu" .Importance = olImportanceHigh .ReadReceiptRequested = True End With Dim sItem As Object Set sItem = CreateObject("Redemption.SafeMailItem") sItem.item = olMail Tag = sItem.GetIDsFromNames("{00020386-0000-0000-C000-000000000046 +}", "X-Reported-Via") Tag = Tag Or &H1E 'the type is PT_STRING8 With sItem .Fields(Tag) = "Test::Reporter Test::Reporter::Transport::Outl +ook" .Subject = sItem.Subject 'to trick Outlook into thinking that + something has changed .Send End With Set olMail = Nothing End Sub

And here is the related Perl (omitted the part that works fine) code:

my $tag = Win32::OLE::Variant->new( VT_R8, $self->{message}->GetIDsFro +mNames( '{00020386-0000-0000-C000-000000000046}', $name )); # converting the numeric value to binary and back to decimal my $pt_string8 = unpack( "B*", pack( "N", 0x0000001E ) ); my $tag_bin = unpack( "B*", pack( "N", $tag->Value() ) ); my $test = $tag_bin | $pt_string8; $self->{message}->Fields->Put( oct("0b$test"), $value);

When running this code I got the following message:

Can't call method "Put" on an undefined value

The concept that I'm missing is related of how to deal with Fields: documentation of Redemption says that Fields is an array, but even in VBA I cannot see it's content with the debugger and cannot loop over it. I can access the value only if I supply the "tag" as the index of it.

In Perl, I cannot dump the value of Fields by using the debugger too (all I got is the nice "Matrix" effect with it).

In truth, I don't know how to setup values for Fields because I don't if for Win32::OLE it is a property, a method or a cheeseburger. I don't know if I should call a method of it, setup a index like an ordinary array, create an array and associate it's value with it. I tried all these things without success.

I tried this:

$self->{message}->Fields( oct("0b$test"), $value);

and got no error (but no extra header too!).

From Perl side, it's necessary to convert values from/to Perl and COM objects. Win32::OLE does almost everything and when it's not enough, Win32::OLE::Variant module does it. I tried creating an ordinary array, associating it's "tag" with the value I want for the extra header, but Perl just dies:

my $array = Win32::OLE::Variant->new( VT_BSTR | VT_ARRAY, oct("0b$test +") );
Win32::OLE(0.1709): Win32::OLE::Variant->new() could not allocate SafeArray

Maybe if I got more details about how Fields was implemented, then I could look for how to integrate Perl code with it. Any advice about that should help.

I'm using ActivePerl 5.10.0 in a Windows XP SP3 with MS Outlook 2003 SP3

Updated:

Fields is a indexed property and should be set with the Win32:OLE method LetProperty method.

That said, the following code works fine:

use Win32::OLE::Variant; my $tag = Win32::OLE::Variant->new( VT_R8, $self->{message} ->GetIDsFromNames( '{00020386-0000-0000-C000-000000000046}', + $name ) ); # When using GetIDsFromNames you must OR the result you get back with +the type of property tag, # in this case PT_STRING8. # PT_STRING8 == 0x0000001E # in binary my $pt_string8 = unpack( "B*", pack( "N", 0x0000001E ) ); my $tag_bin = unpack( "B*", pack( "N", $tag->Value() ) ); my $test = $tag_bin | $pt_string8; $test = oct("0b$test"); #$self->{message}->{Fields} = $array->Value(); #$self->{message}->{Fields}->[$test] = $value; $self->{message}->LetProperty('Fields', $test, $value);
Alceu Rodrigues de Freitas Junior
---------------------------------
"You have enemies? Good. That means you've stood up for something, sometime in your life." - Sir Winston Churchill

Replies are listed 'Best First'.
Re: How to set an extra header with Outlook and Redemption in email messages?
by Anonymous Monk on Mar 13, 2009 at 06:32 UTC
    Try
    $self->{message}->Fields( oct("0b$test") ) = $value;

      Nope... this does not work:

      Can't modify non-lvalue subroutine call at C:/Perl/site/lib/Mail/Outlook/MessageRedempted.pm line 349.
      Alceu Rodrigues de Freitas Junior
      ---------------------------------
      "You have enemies? Good. That means you've stood up for something, sometime in your life." - Sir Winston Churchill
Re: How to set an extra header with Outlook and Redemption in email messages?
by Anonymous Monk on Mar 13, 2009 at 06:37 UTC
    In truth, I don't know how to setup values for Fields because I don't if for Win32::OLE it is a property, a method or a cheeseburger.

    It should be the same (Property/method/cheeseburger) regardless of language (perl/vb/java...).

      I agree with you, but this is not working as expected. Since Fields seems to be an index property, I tried the following:

      my $pt_string8 = unpack( "B*", pack( "N", 0x0000001E ) ); my $tag_bin = unpack( "B*", pack( "N", $tag->Value() ) ); my $test = $tag_bin | $pt_string8; $test = oct("0b$test"); $self->{message}->{Fields}[$test] = $value;

      And that's what I got from this naive approach:

      Out of memory during array extend at C:/Perl/site/lib/Mail/Outlook/MessageRedempted.pm line 351.

      The calculated number of $test will be something like "-2086076386", which Perl thinks it a too big index number to deal with. The problem is, Fields will need this index to be updated.

      There is any way to make Perl access this index without trying to create a complete set of index before updating the desired index value?

      Alceu Rodrigues de Freitas Junior
      ---------------------------------
      "You have enemies? Good. That means you've stood up for something, sometime in your life." - Sir Winston Churchill