English (United States) Magyar (Magyarország)
You are hereBlogs
Register   |  Login
  
  
  

Nagyjából két éve írtam egy cikket "Bevezetés az SMTP EventSink világába rendszergazdáknak" címmel itt a honlapomon. Ez a cikk alapvetően a script író, programozó kedvű rendszergazdákat célozta meg akik a Microsoft Exchnage 2000/2003 környezetben (ide értendő a Microsoft Windows 2000/2003 IIS SMTP szervere is) valamilyen okból bele akartak nyúlni a rendszeren áthaladó e-mailekbe. Azóta a világ sokat változott és benne én is. Megjelent az Exchange 2007, ami teljesen új alapokra helyezi a Windowsos világ üzenetkezelését, valamint én is sokat tanultam, fejlődtem ebben a témakörben amit szeretnék itt és most közzétenni.
Ez a cikk tekinthető a fent említett darab 2.0-ás változatának. Tartalmazza az összes információt ami abban a cikkben megtalálható volt, továbbá sok pontosítást és kiegészítést amire az évek során jöttem rá, szedtem össze információmorzsákból. Ezen túl az Exchange 2003 oldalán átvezet a .NET világba betekintést nyújtva abba a lehetőségbe, hogy script nyelvek helyett .NET-ben írjunk SMTP eseménykezelőket, valamint átvezet az Exchange 2007 ide vonatkozó technológiai (Transport Rule-ok és a Transport Agentek) világába.
1. Bevezetés az SMTP EventSink világába
A Microsoft Exchange Server 2000/2003 és az alatta található Windows Server komponensei (IIS SMTP szerver) lehetőséget kínálnak arra, hogy a rajtuk áthaladó levelekhez programozottan hozzá tudjunk nyúlni. Ezt különböző bonyolultsággal és ebből következően különböző lehetőségekkel tehetjük meg.
Ezek közül a lehetőségek közül, először azt szeretném bemutatni ahol egy egyszerű VBScript vagy JScript kódból bele tudunk nyúlni a rendszerünkbe beérkező és onnan kimenő levelekbe.
Ehhez az Exchange által használt SMTP szerverhez kell egy beépülő modult írnunk és regisztrálnunk. Ez a modul lesz az úgy nevezett SMTP EventSink. Az SMTP levélküldés folyamatába több ponton lehet beavatkozni. Ezek közül most csak azzal az egy pontal foglalkozunk amihez script nyelven is hozzá lehet férni. Az összes pont COM eseménykezelőként érhető el, ezek közül egyhez (OnTransportSubmission vagy más néven OnArrival) készült egy script host (CDO.SS_SMTPOnArrivalSink), amit regisztrálni tudunk a saját scriptünk helyett és ennek a script hostnak adjuk meg paraméterként a végrehajtandó script nevét.
A scriptünk így fog kinézni:

eventsink.vbs

<SCRIPT LANGUAGE="VBSCRIPT">
    Sub ISMTPOnArrival_OnArrival(ByVal Msg, EventStatus)
        ' Ide kerül az EventSink kódja
 End Sub
</SCRIPT>

eventsink.js

<SCRIPT LANGUAGE="JSCRIPT">
    function ISMTPOnArrival::OnArrival(Msg, EventStatus)
    {
        // Ide kerül az EventSink kódja
    }
</SCRIPT>

Az eseménykezelőnk két paramétert kap. Az egyik egy CDO.Message objektum ami tartalmazza a teljes e-mailt. Leírása itt található: CDOEX IMessage Interface. A másik egy EventStatus nevű változó, amin keresztül jelezhetjük a rendszernek, hogy a mi eseménykezelőnk lefuttatása után a hátralévő még sorban lévő eseménykezelőket lefutassa e.
Azzal, hogy megírtuk az eseménykezelő scriptünket még nem vagyunk kész, ugyanis ezt regisztrálnunk kell az általunk kiválasztott SMTP Virtual Serveren. Erre a regisztrációra a Microsoft által írt SMTPREG.VBS script használható. Ebből a scriptből az évek során alapvetően két verzió készült. Az egyik (egyszerűbb) kiadás része az Exchange SDK Documentation And Samples csomagnak, telepítés után a C:\Program Files\Exchange SDK\SDK\Support\CDO\Scripts könyvtárban található (Ha valaki nem akar bíbelődni az egész SDK-val akkor csak magát a scriptet letöltheti innen). Ez a verzió jól használható azok számára akik kizárólag script nyelven írnak eseménykezelőt, ugyanis ezzel, csak a korábban már említett OnArrival eseményre lehet feliratkozni, ugyanakkor könnyebbséget jelent, hogy a regisztrációk listázásánál nem kapjuk meg feleslegesen az egyéb eseményekre regisztrált számtalan Exchange eseménykezelő listáját. A másik verzió ami teljes funkcionalitással használható itt érhető el, valamint a teljesség kedvéért a saját oldalamra is kiraktam ide. Abban az esetben, ha nem script nyelven írunk eseménykezelőt és nem az OnArrival eseményre szeretnénk feliratkozni mindenképp ez utóbbit kell használnunk.

Most néhány példán keresztül bemutatom az smtpreg.vbs használatát.

Meg tudjuk vele nézni, hogy jelenleg milyen eseménykezelők vannak regisztrálva:

cscript smtpreg.vbs /enum

Tudunk regisztrálni eseménykezelőt:

cscript smtpreg.vbs /add 

Nézzük meg, hogy mit is jelentenek ezek a paraméterek:

<Virtual Server> Az SMTP Virtual Server azonosítója. Ez az azonosító egy szám, a Default Virtual Server esetén 1.
<Sink> Az eseménykezelő interfész neve, script esetén mindíg onarrival
<Név> Az eseménykezelőnk saját neve. Ez teljesen szabadon választott, ezzel a névvel tudunk hivatkozni az eseménykezelőnkre.
<Eseménykezelő> A regisztrálandó COM Event handler neve. Ha scriptet akarunk használni, akkor a scripting host neve. Esetünkben mindíg CDO.SS_SMTPOmArrivalSink.
<Protokol szűrő> Az SMTP protokolban használt küldőre (mail from=) és címzettre (rcpt to=) használható szűrő. Ezzel a szűrővel tudjuk meghatározni, hogy mely levelekre hajtódjon végre az eseménykezelő (pl. az összes levélre: "mail from=*").


Tudunk eseménykezelőt törölni:

cscript smtpreg.vbs /remove 

Tudunk az eseménykezelőnkhöz különböző plusz paramétereket adni:

cscript smtpreg.vbs /add <Virtual Server> <Sink>
	<Név> <Eseménykezelő> <Protokol szűrő>

Ezekről a paraméterekről két fontos dolgot kell még tudnunk. Sajnos az itt beállított paraméterek lekérdezésére az általunk írt scriptekből nincs lehetőségünk (A Microsoft által írt scripting host ezeket a paramétereket nem adja át a scriptünknek). Fontos ugyanakkor tudnunk, hogy nekünk a scriptünk regisztrációjakor meg kell adnunk egy paramétert, ami a scripting host-nak mondja meg, hogy hol találja a végrehajtandó scriptet.

<paraméter neve> A COM eseménykezelőnek átadandó paraméter neve. Script regisztráció esetén kötelező a script nevét átadni. Esetünkben ez ScriptName lesz.
<paraméter értéke> A COM eseménykezelőnek átadandó paraméter értéke. Script regisztráció esetén kötelező a script nevét átadni. Esetünkben az értéke a scriptünk neve lesz, teljes elérési úttal.


Minden további magyarázat helyett lássunk egy példát:

cscript smtpreg.vbs /add 1 OnArrival Disclaimer
	CDO.SS_SMTPOnArrivalSink "mail from=*"
cscript smtpreg.vbs /setprop 1 OnArrival Disclaimer
	Sink ScriptName "c:\Scripts\SMTP\disclaimer\disclaimer.js"

Ha regisztráció után elkezdjük használni az első eseménykezelőnket, meglepetten fogjuk tapasztalni, hogy az csak a bejövő leveleinkre hajtódik végre. Sem a kimenő leveleinken, sem a belső Exchange felhasználók közötti leveleken nem hajtódik végre. Ez ugye azon kliens programokból küldött levelekre vonatkozik melyek nem SMTP-t vagy Pickup könyvtárat használnak küldésre, hanem natív MAPI kapcsolaton keresztül küldik a leveleket (Outlook, OWA, OMA, stb.).
Mi ennek az oka? A jelenség ismert a Mcrosoft KB 273233 cikk foglalkozik vele részletesen. Saját tapasztalataim ugyanakkor azt mutatják, hogy az említett cikk hiányos.
Először is szeretnék eloszlatni egy tévhitet (saját magam is rosszul gondoltam jó ideig):
Az általános vélekedéssel ellentétben azok a levelek amiket egy Exchange felhasználó küld egy másik Exchange felhasználónak még abban az esetben is amikor azonos adatbázisban található a mailboxuk áthaladnak az SMTP Transporton. Ha ez így van, tehát minden levél áthalad az SMTP Transporton, akkor az eseménykezelőnk miért nem hajtódik végre a kimenő és az átmenő leveleken?
Ennak alapvetően két oka van:
1. Ezek a levelek az SMTP Szervernek csak a transport részén haladnak át és a protokol részén nem. Ezzel alapvetően még nem is lenne baj, mert az eseménykezelőnk nem az SMTP protokol utasításait figyeli, hanem azokat a leveleket amiket az SMTP szerver már teljesen átvett, tehát a transport fázisba jutottak. A gond az eseménykezelőnk regisztrációjánál van. Azokon a leveleken amik nem haladtak át a protokol szakaszon nem található meg az SMTP boríték, ezért ezeken a leveleken nem tudjuk érvényesíteni a regsztrációnál megadott protokol szabályt (pl. "mail from=*"). Sebaj mondhatnánk, akkor regisztráljunk szabály nélkül, vagy üres szabállyal. Ez nem fog működni. Az első esetben az smtpreg.vbs hibát ad, a második esetben viszont létrehozza a regisztrációt, de benne lesz a szabály (rule) üresen, így változatlanul nem hajtódik végre az eseménykezelőnk az említett leveleken. Hogyan lehet ezt kikerülni? Egyszerűen. Kicsit bele kell javítani az eredeti smtpreg.vbs-be például úgy, hogy ha üres szabályt adunk meg akkor ne is regisztrálja azt. Nem kell megijedni, nem kell megkeresni az smtpreg.vbs kódjában, hogy mibe is kellene belenyúlni, mert én ezt már megtettem. A módosított verzió letölthető innen. Ha ennek a változatnak üres rule-t adunk meg akkor nem fog rule-t regisztrálni.
2. A második probléma már keményebb dió. Itt jön be először is amit a KB cikk ír, az, hogy a rendszer eldobja azt az üzenet példányt amit nekünk mint eseménykezelőnek átadott, így a módosításaink elvesznek. A helyzet sajnos ennél sokkal rosszabb. Nem is tudunk mit kezdeni az átadott levéllel, ugyanis a levéltovábbításnak ebben a szakaszában még nem történt meg a TNEF/MIME konverzió (a TNEF az Exchange által használt belső formátum) és eszközünk sincs arra, hogy ezt scriptből megtegyük.
Ezt a problémát kétféleképpen tudjuk áthidalni. Az egyik megoldás, hogy maradunk a script nyelveknél és az SMTP Virtual Serverekkel trükközünk, a másik, hogy elhagyjuk a script nyelveket és C/C++-ban, vagy .NET-ben írjuk meg az eseménykezelőnket és azt az OnArrival helyett az OnPostCategorize eseményre regisztráljuk.
Először nézzük meg, hogyan tudjuk a kérdést megoldani az SMTP Virtual Serverek konfigurációjával. Előre kell bocsátanom, hogy ilyen módon a belső leveleket nem fogjuk tudni kezelni, csak azokat amik az Exchange-ből kifelé haladnak.
Az elv az, hogy létre kell hoznunk egy második SMTP virtual server-t és át kell irányítanunk minden levelet az első virtual server-ről a másodikra. Ezek után az eseménykezelőnket a második SMTP virtual server-re telepítjük. Ez biztosítja, hogy mire az eseménykezelőnk végrehajtódik a levél MIME formátumú legyen.
A következő lépésekben létre fogunk hozni egy második SMTP virtual servert ami a szabványos 25-ös TCP port helyett egy másik porton figyel (pl. a 26-oson) és a szabványos 25-ös porton küldi a leveleket. A default SMTP virtual server pedig a 25-ös TCP porton figyel és a 26-os TCP porton küldi ki a leveleket, amit a második SMTP virutal server fog átvenni. Alapvetően bármilyen levél halad át, annak a default SMTP virtual server-re kell megérkeznie. Ha a levél belső címre irányul akkor azt a default SMTP virtual server kézbesíti és nem halad át a második SMTP virtual serveren. Ha a levelet kifelé kell kézbesíteni akkor a default SMTP virtual server átaja a második SMTP virtual servernek.
1. Nyissuk ki az Exchange System Manager-t és navigáljunk az SMTP mappához. Ez a mappa a First Administrative Group/Servers/szerver neve/Protocols/SMTP.
2. Kattintsunk a jobb egérgombbal a mappára, majd a New menüpontra, majd az SMTP Virtual Server menüpontra.
3. Írjuk be az új virtual server nevét és nyomjuk meg a Next gombot. IP címnek adjuk meg az All Unassigned bejegyzést és nyomjuk meg a Finish gombot. Egy figyelmeztető ablakot fogunk kapni arról, hogy a szerver nem fog elindulni az ütköző IP címek és portok miatt. Ezt a figyelmeztetést figyelmen kívül hagyhatjuk. Nyomjuk meg a Yes gombot.
4. Kattintsunk jobb egérgombbal egyenként a virtual server-ekre és utána válasszuk ki a Stop menüpontot.
5. Kattintsunk jobb egérgombbal a default SMTP virtual server-re és válasszuk ki a Properties menüpontot.
6. A Delivery fülön kattintsunk az Advanced gombra. A Smart host szövegdobozba írjuk be a gépnek azt a teljes domain nevét ami pontosan a Smart host szövegdoboz fölött található, vagy a szerver IP címét szögletes zárójelbe foglalva, majd kattinsunk az OK gombra. A Delivery fülön kattinsunk az Outbound connections gombra. A TCP szövegdobozba írjuk be a 26-ot és kattintsunk az OK gombra. Kattintsunk az OK gombra a párbeszédablak becsukásához.
7. Kattintsunk jobb egérgombbal a másik SMTP virtual server-re és válasszuk ki a Properties menüpontot. A General fülön kattintsunk az Advanced gombra válaszuk ki az All Unassigned sort. Kattintsunk az Edit gombra, változtassuk meg a TCP portot 26-ra és kattintsunk az OK gombra. Kattintsunk mégegyszer az OK gombra.
8. Kattintsunk az Access fülre, majd a Relay gombra, majd adjuk hozzá az engedélyezett gépek listájához a gépünk IP címét és a 127.0.0.1-es címet. Kattintsunk az OK gombra majd mégegyszer az OK a párbeszédablak bezárásához.
9. Kattintsunk jobb egérgombbal egyenként a virtual server-ekre és utána válasszuk ki a Start menüpontot.
10. Regisztráljuk az eseménykezelőnket a második SMTP virtual serverre. Használjuk a következő parancsot:

cscript smtpreg.vbs /add 2 OnArrival PeldaOnArrivalEsemeny
	PeldaSMTPEsemeny.EsemenyInterface "mail from=*"

Vegyük észre, hogy egy 2-es áll az "/add" után ami megmondja a scriptnek, hogy a második SMTP virtual server-re regisztrálja az eseményt. Normál esetben ez 1 az első (default) SMTP virtual server-re.
Ennek a módszernek két szépséghibája van. Az egyik, hogy abban az esetben ha az Exchange szervezetben több szerver is szerepel, akkor a fenti beállítások nem elégségesek és nem is megfelelőek. Ez esetben a beállítások az Exchange routing alapos elméleti szintű ismeretét ígénylik. A másik gond, hogy ez a megoldás az eredeti Microsoft leírások szerint nem üzembiztos, ugyanis az Exchange szerver nem a Default Virtual Serveren keresztül küldi ki a leveleket, hanem azon keresztül amelyik egy rendszerindításnál, vagy a Virtual Serverek kézi indításánál/leállításánál először elindul. Zárójelben jegyezem, hogy nagyjából 5-6 éve használok ilyen módon felépített rendszert és miután a kézi indításnál/leállításnál mindíg kínosan ügyeltem arra, hogy a Default Virtual Servert indítsam el először, soha nem volt problémám abból, hogy esetleg az Exchange rossz Virtual Serveren keresztül küldte volna ki a leveleket.
folyt. köv...

 Comments

In order to add comments, you must register on the site. Simply select the Register link in the top right portion of the screen and enter your contact information. Once you are logged-in, you will be able to add comments.

Already registered? Click here to login to the site. 

 

 Keresés