API - .Net - Entwürfe und gesendete Mails eindeutig zuordnen

  • Hallo.

    Ich gebe auf und suche Hilfe.
    Ich versuche seit mehreren Wochen eine Gesendete Email eineindeutig zu dem entsprechenden Entwurf zuzuordnen. Ohne Erfolg.

    zuerst: Ich Programmiere in C#, verstehe aber auch die anderen gängigen Sprachen a la c++, VB, VB.net, java, jscript...

    Was ich bisher versucht und erreicht habe:

    David-Mail erstellen, (Ob nun als MailItem, MessageItem2 oder sonstwie ist mir relativ egal)
    in Entwürfen speichern,
    auf das Entwüfe_NeueMail-Event reagieren (zu diesem Zeitpunkt ist David mit dem speichern der mail fertig)
    und die Mail via Process.Start anzeigen

    Ich bin auf dem Ausgang_NeueMail-Event registriert und kann mir die "gesendeten" Emails ausgeben lassen.
    ABER:
    Ich habe keine Ahnung, ob ich (mein Programm) die Gesendete Mail erstellt hat, oder der User, oder wer-auch-immer.


    Was ich möchte:
    Ich würde gerne die Mail Identifizieren, um a) die "Entwurfs-Mail" zu löschen, und b) die Gesendete Mail (.eml) zu speichern.


    Meine bisherigen Versuche (und woran sie gescheitert sind):

    Achja, Was ich vergessen habe zu erwähnen: die _ID (RecNo, QID oder wie man sie auch nennen mag) ist
    natürlich bei dem Entwurf und dem gesendeten Objekt verschieden.

    UserField definieren ( in beiden Archiven _Drafts und _Out ), und in diesem Feld bei Email Erstellung MailItem ne ID sichern,
    um diese dann aus dem Gesendeten Objekt auszulesen und so die Mail zu Identifizieren.
    --> Gesendetes Objekt hat das UserField nicht --> problem ;)

    Das selbe in grün, diesmal nicht mit einem MailItem, sondern mit einem MessageItem2,
    in der hoffnung, das dieses mehr kann (habe immernoch die #define MailItem-Weiche)
    --> Natürlich nicht, immernoch kein UserField in der Gesendeten Mail --> problem ;)

    (UserFields werden wohl nicht "mitkopiert" :( )

    Ein "ungenutztes" Field mit meiner ID füllen und dann in der Gesendeten auslesen,
    (habe bei der erstellung in alle leeren Felder (MessageItem2 mit (is string und == String.Empty,
    bzw. is int und == -1 oder 0)) gesschrieben, jedoch hatte das Gesendete MessageItem alle
    Felder "zurueckgesetzt" --> Keine ID füer mich --> Problem ;)

    Mail mithilfe des Inhalts (Empfänger - HTML Text etc.) zu identifizieren
    --> Kann ich nciht machen, der User kann den Entwurf überarbeiten --> problem ;)


    Was ich noch im Netz gelesen habe (und warum es nicht funktioniert):

    Einfach das Item im _Out - Archiv nehmen, welches die "höchste" ID hat
    --> danke, aber ich möchte nicht "die neuste" gesendete Email haben, sondern "meine" --> problem ;)

    Die Email nocheinam zusätzlich vor dem Versand in ein Archiv (möglichst selbst anlegen)
    kopieren, und dann alle Emails in dem Archiv Serialisieren / überwachen
    --> zum Einen verschiebt das nur das Problem (identifiziere NeuesArchiv.Mail mit _Out.Mail),
    zum anderen möchte ich ja gerade nicht den Entwurf spreichern, sondern die gesendete
    und moeglicherweise geaenderte Mail Speichern. --> problem ;)


    Was vielleicht Funktionieren könnte (was meint Ihr);

    für jeden Benutzer in David (auch via API übrigens, wenns geht), einen "Schattenbenutzer" einrichten,
    und diesem immer eine Kopie der Email zuschicken (bcc oder wie das heisst);
    Sofern der User den Kopieempfänger nicht löscht, kann ich in dem
    SchattenUser-Posteingang meine Emails finden, okay, ich muss die immernoch zuordnen,
    aber ich bin einen Schritt weiter (keine "anderen" mails mehr)
    --> Sehr viel Aufwand, Identifizierungs-Problem bleibt --> problem ;)

    Via JavaSkript das David-Menü erweitern, den (dann hoffentlich globalen)
    daraus resultierenden "Mein-Senden"-Befehl bzw. Event abonieren,
    und dann die "nächste" gesendete Mail speichern.
    --> problem beim gleichzeitigen Senden Mehrerer mails
    und das klingt recht aufwendig --> problem ;)


    Email nicht als Entwurf zum Versenden erstellen (und anzeigen)
    sondern im Ausgang im Wartemodus.
    --> Ich meine ich bekomme a) kein "gesendet" event, und
    b) bin ich mir gerade nicht sicher, ob der User die Mail dann noch bearbeiten kann
    --> Sollte ich mal durchprüfen


    Meine ID nicht in ein Feld, sondern in die Mail schreiben (HTML-Content,
    vielleicht als Kommentar oder Weiß auf weiß oder so [muss zugeben, mein HTML ist etwas eingerostet])
    und dann die Gesendeten Mails daraufhin untersuchen
    --> Der Benutzer kann die Mail ja überarbeiten,
    aber falls ich "unsichtbare" Elemente nehme, hätte ich ne chance...
    --> Das könnte vllt. wirklich klappen


    Das Tobit-Team solange nerven, bis die die Möglichkeit schaffen,
    bei UserFields, die in "beiden" Archiven existieren, diese auch zu "kopieren",
    möglichst inklusive inhalt (wobei mir erstmal der Name des Feldes genügte)
    --> Eher Unwahrscheinlich, aber warum ist das zurzeit nicht so?


    Job kündigen, bei Tobit anheuern, hocharbeiten,
    selber die eben besprochene Funktion implementieren,
    kündigen, wieder anfangen wo ich nun arbeite
    --> Könnte klappen, ist aber etwas umständlich, und sehr
    zeitaufwendig


    Fazit:
    Problem bleibt ungelöst, und ich bin für jede Eingebung dankbar.
    Dabei muss es sich nicht um Code an sich handeln, ein guter Weg
    ist mir ebenso wilkommen.


    Falls es bereits eine Lösung geben sollte, bitte ich um Gnade für
    den DoppelThread (habe die Forensuche vor erstellung bemüht).

    Ich glaube ich kann nicht der erste sein mit diesem Problem,
    vermutlich ist die Lösung viel, viel einfacher als ich denke.

    tl;dr
    Brauche Hilfe bei der Identifizierung gesendeter Mails zu Erstellten Entwürfen.
    David 'kopiert' die UserFields wohl beim Senden nicht aus den Entwürfen.

    MfG, Mathias.

    p.s.: sry für die vielen TrollFace - war wohl zu lange auf 9gag gestern.

  • Hallo,

    Wenn ich das richtig verstehe, ist das Hauptproblem, dass beim normalen Speichern
    der Vorgang asynchron verläuft und man dann nicht weiß welcher Eintrag das im
    Zielordner ist und eventuell, ob er dort überhaupt angekommen ist.Man kann aber
    eine eMail auch synchron speichern per API.
    Beispiel (ich versuche es mal in C#):

    Code
    Archive oArchive = oAccount.GetSpecialArchive(DvArchiveTypes.DvArchivePersonalDrafts);MailItem oItem = oArchive.NewItem(DvItemTypes.DvEMailItem);oItem.Subject = "Test";oItem.BodyText.PlainText = "Body";oItem.Recipients.Add("test@test.de");// ... weitere Angaben der Einfachheit halber weggelassenoItem.Save(null, DvMessageSelectionTypes.DvMsgSelDirect);


    Die Angabe DvMsgSelDirect bewirkt, dass die Methode erst zurückkehrt, nachdem sie das
    Objekt gespeichert hat. Das heißt, dass dann auch z.B. die Record Nummer bekannt ist.
    Also würde direkt nach dem Speichern funktionieren:

    Code
    Fields oFields = oItem.Fields;int recno = oFields.Item("recno").Value;


    Die Idee, die eigene Mail um ein Benutzerfeld zu erweitern, um sie auch später eindeutig
    identifizieren zu können, ist nicht schlecht und ließe sich so bewerktstelligen:
    Vor dem Speichern

    Code
    Fields oFields = oItem.Fields;FieldDefinition oDef = oFields.UserFields.CreateDefinition("Test", DvFieldType.DvFieldText);oFields.UserFields.Add(oDef, "Wert");


    Und wenn das Objekt wieder eingelesen wird:

    Code
    oItem = (MailItem)oArchive.ItemFromID(recno, 34);oFields = oItem.Fields;if (oFields.UserFields.Item("Test").Value != "Wert"){// Ist nicht mein Objekt}


    Und nun zu dem zweiten Problem. Die eMail soll auch versendet werden und im Ausgang
    bzw. im Transit dasselbe Benutzerfeld haben, wie die gespeicherte eMail.
    Dann könnte man direkt nach dem Speichern also nach oItem.Save(null, DvMessageSelectionTypes.DvMsgSelDirect);
    einfach nochmal das gleiche Feld hinzufügen und dasselbe Objekt versenden:

    Code
    Fields oFields = oItem.Fields;
    FieldDefinition oDef = oFields.UserFields.CreateDefinition("Test", DvFieldType.DvFieldText);
    oFields.UserFields.Add(oDef, "Wert");
    oItem.Send();


    Nun sollte die Mail, wenn sie im Ausgang landet, dasselbe Feld haben, wie
    die in den Entwürfen.

    Ich bin mir nicht sicher, ob das die Antwort auf das Problem ist.
    Aber vielleicht hilft das schon mal weiter.
    MFG

  • Hallo und danke für die Antwort,

    Code
    oItem.Save(null, DvMessageSelectionTypes.DvMsgSelDirect);

    hört sich zwar gut an, aber ich fürchte, dass meine "App" dann lagged, da mein Thread "ohne Reaktion" auf David wartet,
    von daher hatte ich mich für die Event-Lösung entschieden (Ich bekomme mit, wenn es ein neues Element im Entwürfe-Ordner gibt),
    soweit klappt es ja auch. Der Mail noch das UserField mitzugeben und dort eine ID zu hinterlegen klappt ja auch.

    Problematisch wirds, wenn die Mail "abgeschickt" wird.

    Ich bekomme zwar ein Event, welches auf das hinzufügen einer Mail im "Gesendet" (kann auch sein das das Archiv Ausgagng heisst),
    Archiv reagiert, weiß jedoch nicht, ob das die von meinem Programm erstellte Mail, oder etwa eine vom Nutzer erstellte Mail war.

    Die Mail in dem Gesendet-Archiv hat leider
    a) eine andere RecNo als die Entwurfs-Mail und
    b) kein UserField.

    So dass ich die Mail nicht zuordnen kann. Und genau das ist das Problem.

    Ich werde das dennoch nocheinmal versuchen, der Unterschied von deinem Code
    hin zu meinem ist das ich das UserField mit

    Code
    vArchive.FieldDefinitions.Add(MyPropName, DvFieldType.DvFieldText);

    , also auf Archiv.AddUserFieldDefinition. hinzufuege und du auf der vItem.AddUserFieldDefinition - Ebene.
    Ich denke aber nicht, das dies etwas ändert.
    (zumal nach dem Speichern der Mail, ich ja das UserFeld fuer testzwecke derzeit auch noch auslese,
    also das UserField vItem.Fields als Fields.UserField.GetItem(MyPropName)

    bzw. eigendlich

    Code
    private static string GetUserpropertyFromMessage(MessageItem2 Item)    	{        	string result = null;        	var fields = Item.Fields as Fields;        	var userFields = fields.UserFields;        	foreach (Field fld in userFields)        	{            	if (fld != null)            	{                	if (fld.Name == MyPropName)                	{                    	result = fld.Value as string;                    	Marshal.ReleaseComObject(fld);                    	break;                	}                	Marshal.ReleaseComObject(fld);            	}        	}        	Marshal.ReleaseComObject(userFields);        	Marshal.ReleaseComObject(fields);        	return result;    	}

    meinen erwarteten Identifikator zurueckgibt.)

    MfG


    Jupp, gerade durchgetestet, leider auch keine Abhilfe :(

    mein Output:

    Code
    Msg before Save
    Msg._ID is 	263
    Msg.Subject is 	Mail Subject 16:39
    Msg after Save
    Msg._ID is 	263
    Msg.Subject is 	Mail Subject 16:39
    UserProp KS21MsgGuid ist c5514e31-6f82-4dd5-994f-9ac9b47de6a3
    Invoke required
    ArchiveNotification_ItemNewEvent_Out_ // Das Neues Objekt im Ausgang-Event
    ID der Msg ist: 296

    Einmal editiert, zuletzt von [KS21] Kosi (25. Mai 2012 um 16:41)

  • Hallo,
    was ich vergessen habe zu sagen, mein Beispiel funktioniert nur mit David.FX 12 ab einem bestimmten
    Service Release - ich weiß nicht genau welches. Das ist also so mit dem ersten Release von David.FX
    nicht möglich.
    Ein kleiner Unterschied besteht schon, wenn man die Felddefinition auf einem Archive Objekt
    hinzufügt. Deine Variante legt die Definition als eine Art Template ab, die dann auch von
    anderen benutzt werden kann. Das heißt, es wird eine Datei archive.def in dem Ordner
    erzeugt, in der diese Defintion steht. Das ist meines Erachtens überflüssig, aber auch nicht schlimm.
    MFG

  • Hallo Heraklitos und danke nochmal für deine Zeit,

    ich habe zwischenzeitig an anderen Problemen gesessen, und daher noch nicht geantwortet.
    Leider klappt dein Vorschlag auch nach dem Update auf den aktuellsten Stand (März 2012 glaube ich) nicht.

    Das Problem liegt immer noch an der "wechselnden" RecNo (bzw. _ID), der Entwurfs- und der Gesendet-Nachricht.

    Zwar kann ich den Entwurf speichern und Anzeigen (was ich ja auch mache), aber wenn der Nutzer die Email verschickt,

    wird quasi eine Kopie des Entwurfs erstellt, die
    a) eine andere _ID besitzt und
    b) die UserProp, die ich in der Entwurfs-Mail angelegt hatte, nicht besitzt :(

    Damit habe ich m.E. keine Möglichkeit den Entwurf mit der gesendeten Mail zweifelsfrei zu Identifizieren.

    Ich werde versuchen im HTML-Teil des Entwurfs ein (nicht sichtbares) Feld anzulegen, und dort meine
    Guid zu hinterlegen. So kann ich, wenn ich Glück habe, (und damit meine ich a) der Nutzer nicht mit [STRG]A alles löscht
    und b) "unnötige" HTML-Elemente in der Entwurf->Transit-Mail kopiert wird) die Gesendeten Mails darauf hin prüfen,
    und so viele Mails identifizieren. Aber schön ist anders.

    Wie gesagt, Problem noch nicht gelöst, eher einen Workaround erdacht (und ob das klappt?),
    also, Thread ist noch offen, Hilfe immer noch willkommen.

    MfG, Mathias

    p.s.:

    Code
    int recno = oFields.Item("recno").Value;
    var oItem = (MailItem)oArchive.ItemFromID(recno, 34);

    Die RecNo ist halt gerade nicht gleich bei einem Entwurf und der damit erstellten Email.

  • Zitat

    Damit habe ich m.E. keine Möglichkeit den Entwurf mit der gesendeten Mail zweifelsfrei zu Identifizieren.

    Wenn eine ID als Primary Key nicht zur Verfügung steht, bleibt immer noch die Variante eines kombinierten Schlüssels,
    z.B. aus Absender + Empfänger + Betreff + einem Teil der Nachricht selbst.

    Alternativ füge im Mailtext ganz unten nach Signatur und Co. noch eine eindeutige ID ein, die Du noch einmal suchst. Wenn's HTML ist dann vielleicht auch unsichtbar.

    Wenn Du dann im Ausgangsordner von neu nach alt suchst, solltest Du Deine Mail relativ schnell finden.

  • Naja,

    das ist auch meine derzeitige Vorgehensweise;

    Ich versuche händeringend mithilfe verschiedener Informationen
    (Datum, Sender, Empfänger, Teil des Betreffs, BodyText- Wörter der Gesendeten Emails
    stimmen zu >80% mit den erwarteten (den aus dem Entwurf) BodyText-Wörter der mir bekannten
    Entwurfs-Mail überein)
    die Email zu Identifizieren, aber da es sich bei der von uns erstellten Email und einen Entwurf handelt
    ist es nicht unwahrscheinlich, dass "alles" geändert wird.

    (Falsche Email-Empfänger-Addy wird korrigiert, Inhalt wird editiert, Email wird erst nach "stunden" versandt,
    zwischendurch werden u.U. viele andere Emails, von unserem Programm oder manuell angelegt, versendet
    und und und.)

    Ich meine ich baue keine Raketensteuerung, insofern ist es nicht Kriegsentscheidend, jedoch werden unsere Kunden
    unseren Support beschäftigen, wenn mal eine Email mal nicht archiviert wird...

    Als nächstes schaue ich nach einem HTML-Tag, der nicht im Text auftaucht, und sichere dort meinen Key ein weiteres mal,
    dann haben wir gute Chancen. Aber eine Restungenauigkeit bleibt, und diese führt typischerweise zu Beschwerden

    Und danke für den Beitrag

  • Hallo,

    ich wollte nur kurz erwähnen, das der HTML Teil des MessageItem2-Elemtes
    recht gut Kommentare verträgt und diese auch beim Kopieren der Email beibehalten werden.

    Ich schreibe nun im Setter meines HTMLText - Fields nun auch in das HTML - Field, etwa so:

    Mit dem Ergebnis (Beispiel)
    <META http-equiv=Content-Type content="text/html; charset=utf-8"><!-- MyGuid xxxxxxx-6430-4466-b57c-5953238d5478 -->

    (Der HTML-Comment bleibt auch bei Alles löschen und/oder aus anderen Quellen einfuegen,
    (getestet Dv-Emails, OL-Emails, Word-Dokumente) stehen.

    Dieser Workaround hat zwei leichte Nachteile:
    1) <META http-equiv=Content-Type content=\"text/html; charset=utf-8\"> ist hart ausgecodet, sollte ich evtl. flexibler gestalten, und
    2) der Empfänger "sieht" den Kommentar, falls er sich den HTML-Kontext anschaut. Aber das ist m.E. nicht weiter tragisch.

    Fühlt sich zwar ein wenig unelegant an, aber funktionert soweit.

    Vielen Danke nochmal für die Hilfen und Anregungen, hoffentlich hilft dies auch dem ein oder anderen Anderen.

    Grüße, Mathias

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!