Autor Beitrag
Peter18
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Do 14.11.13 11:57 
Ein freundliches Hallo an alle,

ich habe ein Problem mit der Mapi. Per Programm möchte ich eine Mail vorbereiten, Empfänger, Betreff und Text eintragen. Dann soll der Benutzer die Möglichkeit haben Änderungen und Ergänzungen am Text vorzunehmen, bevor er sie abschickt. Damit das Programm unabhängig vom Mailprogramm funktioniert verwende ich die Mapi. Zum Testen habe ich folgendes Programm mit Delphi 4 geschrieben:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
procedure TForm1.Button1Click(Sender: TObject);
var
  S            : Cardinal;
  MAPISession  : PLHANDLE;
  MapiMessage  : TMapiMessage;
  MapiRecip    : PMapiRecipDesc;
  MapiOrg      : PMapiRecipDesc;

begin
  MapiRecip.lpszName             := PChar( Edit1.Text );
  MapiRecip.lpszAddress          := PChar( Edit2.Text );
  MapiRecip.ulRecipClass         := MAPI_TO;
  MapiOrg.lpszName               := PChar( 'Sender' );
  MapiOrg.lpszAddress            := PChar( 'Sender@Domain.de' );
  MapiOrg.ulRecipClass           := MAPI_ORIG;
  MapiMessage.ulReserved         := 0;
  MapiMessage.lpszSubject        := PChar( Edit3.Text );
  MapiMessage.nFileCount         := 0;
  MapiMessage.lpszNoteText       := PChar( 'Nachricht' );
  MapiMessage.lpszMessageType    := PChar( '' );
  MapiMessage.flFlags            := 0;
  MapiMessage.lpOriginator       := MapiOrg;    
  MapiMessage.lpszDateReceived   := PChar( '' );
  MapiMessage.lpszConversationID := PChar( '' );
  MapiMessage.nRecipCount        := 1;
  MapiMessage.lpRecips           := MapiRecip;

  S := MapiSendMail( 0, Application.Handle, MapiMessage, MAPI_DIALOG or MAPI_LOGON_UI, 0 );
  MessageDlg( 'Result: '+IntToStr( S ), mtConfirmation,  [mbOK], 0 );
end;


Anscheinend stimmt etwas mit den Parametern nicht. Mein Mailprogramm Pegasus wird gestartet, zeigt jedoch keine neue Mail. Es wird auch keine Mail versand. Outlook zeigt das gleiche Verhalten. "S" ist nach dem Aufruf 0. "MSDN" die "Developer-Seiten" und verschiedene Delphi-Foren haben nicht den Durchbruch gebracht.

Warscheinlich sehe ich den Wald nicht, weil zu viele Bäume im Weg rumstehen. Vielleicht kann mir ja jemand eine Brille verpassen.

Dank allen die sich mit dem Problem beschäftigen und Grüße von der Nordsee

Peter
mandras
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 429
Erhaltene Danke: 107

Win 10
Delphi 6 Prof, Delphi 10.4 Prof
BeitragVerfasst: Do 14.11.13 13:02 
Ohne den Code ausprobiert zu haben vermute ich:
MAPISession : PLHANDLE;
MapiRecip : PMapiRecipDesc;
MapiOrg : PMapiRecipDesc;
sind alles Pointer.
Du müßtest denen vorher auf jeden Fall Speicher zuweisen.
Ob dies die Ursache für den Fehler ist weiß ich nicht,
auf jeden Fall würde das Programm jedoch nicht zuverlässig funktionieren.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 14.11.13 13:41 
Die Variablen sind schlicht ungünstig deklariert. Die manuelle Speicherzuweisung kann man sich sparen, wenn man die Variablen nicht als Pointer deklariert...
ausblenden Delphi-Quelltext
1:
2:
  MapiRecip    : TMapiRecipDesc;
  MapiOrg      : TMapiRecipDesc;
An den anderen Stellen muss man dann natürlich bei Bedarf z.B. @MapiRecip benutzen um den Pointer auf die Struktur zu erhalten.
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Do 14.11.13 13:43 
Hallo mandras,

danke für Deine Antwort. Die Pointer haben einen Wert. In keinem Beispiel habe ich ein Allocate gesehen aber:

ausblenden Delphi-Quelltext
1:
FillChar(MapiRecip, SizeOf(MapiRecip), #0);					

Doch nach diesem "Fill" ist der Pointer = nil. In der Delphi-Mapi werden Strukturen deklariert:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
  PMapiRecipDesc = ^TMapiRecipDesc;
  {$EXTERNALSYM MapiRecipDesc}
  MapiRecipDesc = packed record
    ulReserved: Cardinal;       { Reserved for future use                  }
    ulRecipClass: Cardinal;     { Recipient class                          }
                                { MAPI_TO, MAPI_CC, MAPI_BCC, MAPI_ORIG    }
    lpszName: LPSTR;            { Recipient name                           }
    lpszAddress: LPSTR;         { Recipient address (optional)             }
    ulEIDSize: Cardinal;        { Count in bytes of size of pEntryID       }
    lpEntryID: Pointer;         { System-specific recipient reference      }
  end;
  TMapiRecipDesc = MapiRecipDesc;

Damit sollte eigentlich der Speicher reserviert sein.

Grüße von der Nordsee

Peter
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 14.11.13 14:13 
Da ist nichts reserviert. Die Pointer zeigen an eine zufällige Stelle im Speicher, da sie bei dir nie zugewiesen werden. Du schreibst dann in MapiRecip.lpszName und damit irgendwo in den Speicher. Dass das nicht klappen kann, ist klar.

TMapiRecipDesc ist nur die Definition der Struktur, sprich es steht da drin wie die 24 Byte mit den Daten belegt sind. PMapiRecipDesc ist nun ein Pointer auf solche 24 Byte. Wenn du dem Pointer aber nicht die Adresse von reservierten 24 Byte im Speicher zuweist, dann zeigt der an eine zufällige Stelle. Dein Programm kann das an der Stelle nicht wissen und schreibt einfach dahin. Je nachdem was an der Stelle liegt, knallt es gleich, gibt es Fehler an anderer Stelle oder du merkst das Problem nicht sofort (und letzteres ist die größte Gefahr dabei).

Deklarierst du die Variable als TMapiRecipDesc, reserviert Delphi den Speicher für dich und du kannst mit @ die Adresse, also den Pointer, dieses Speicherbereichs bekommen und damit arbeiten.
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Do 14.11.13 14:40 
Hallo jaenicke,

dank auch Dir für die Antwort.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure TForm1.Button1Click(Sender: TObject);
var
  S            : Cardinal;
  MAPISession  : PLHANDLE;
  MapiMessage  : TMapiMessage;
  SMapiRecip   : TMapiRecipDesc;
  SMapiOrg     : TMapiRecipDesc;
  MapiRecip    : PMapiRecipDesc;
  MapiOrg      : PMapiRecipDesc;

begin
  // FillChar(MapiRecip, SizeOf(MapiRecip), #0);
  MapiRecip                      := @SMapiRecip;
  MapiOrg                        := @SMapiOrg;
  MapiRecip.lpszName             := PChar( Edit1.Text );

sollte dann korrekt sein.

Wer lesen kann ist klar im Vorteil. Ich sollte vielleicht etwas sorgfältiger lesen. Leider klapt es mit der Mail noch nicht. Da muß noch etwas faul sein.

Grüße von der Nordsee

Peter
baumina
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 305
Erhaltene Danke: 61

Win 7
Delphi 10.2 Tokyo Enterprise
BeitragVerfasst: Do 14.11.13 14:50 
Also wenn ich mir so Beispielcodes anschaue (wie hier z.B. www.swissdelphicente...howcode.php?id=1246), dann steht da 1. überall erstmal ein FillChar und 2. vor allen PChar-Umwandlungen ein StrNew. Ob das nun dein Problem löst, kann ich dir allerdings nicht beantworten.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 14.11.13 15:10 
user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
[...]
sollte dann korrekt sein.
Ja.

user profile iconbaumina hat folgendes geschrieben Zum zitierten Posting springen:
dann steht da 1. überall erstmal ein FillChar und 2. vor allen PChar-Umwandlungen ein StrNew. Ob das nun dein Problem löst, kann ich dir allerdings nicht beantworten.
StrNew sollte nicht notwendig sein, aber FillChar könnte erforderlich sein, da nicht alle Felder initialisiert werden.
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Do 14.11.13 15:54 
Hallo baumina, hallo jaenicke,

dank Euch für die Antworten. "FillChar" habe ich schon eingebaut und getestet.

Doch nach wie vor klappt es mit der Mail nicht.

Grüße von der Nordsee

Peter
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Do 14.11.13 18:50 
Hallo an alle,

inzwischen habe ich herausgefunden, dass "Pegasus Mail" anscheinend nicht vollständig in der Mapi eingehängt ist oder durch andere Fehler in den Daten nicht funktioniert. Mit Outlook habe ich eine Fenster für neue Mails erhalten. Dort zeigte sich, dass "StrNew" ist erforderlich, da sonst die Strings beschädigt bei dem Programm ankommen. Ebenfalls scheint ein Präfix "SMTP:" erforderlich zu sein, damit alles korrekt eingetragen wird, andernfalls zeigt das Empfängerfeld seltsame Einträge.

Werde weiter experementieren und berichten. Bin für Tipps und Beschreibungen weiterhin dankbar!

Freundliche Grüße von der Nordsee

Peter
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Mi 27.11.13 18:44 
Ein freundliches Hallo an alle,

die Mapi von "Pegasus Mail" ist tatsächlich nicht vollständig implementiert. Der Mapi-Entwickler meint, "MAPI_DIALOG" ist nur für die Anmeldung bei "Exchange" gedacht und ignoriert die Flags bei Sendmail.

ausblenden Delphi-Quelltext
1:
MapiSendMail( 0, Application.Handle, MapiMessage, MAPI_DIALOG or MAPI_LOGON_UI, 0 );					

Daher klappt es nicht wie bei Outlook, dass die Mail gelesen und bearbeitet werden kann.

Grüße von der Nordsee

Peter