Maile ablaufende Domänenkonten

Zweck ist es der Personalabteilung alle innerhalb von 30 Tagen ablaufende Domänenkonten anzuzeigen, damit diese darauf entsprechend reagieren kann.
Dazu muss auf dem Rechner ein C-Compiler (LCC) installiert sein und die beiden aufgeführten Dateien in ein Verzeichnis kopiert werden.
Hier ist der Compiler (http://www.cs.virginia.edu/~lcc-win32) nach c:\programme\LCC installiert.

compile.bat
c:\programme\lcc\bin\lcc -O2 -A -unused -overflowcheck MailExpiredAccounts.c
c:\programme\lcc\bin\lcclnk -s MailExpiredAccounts.obj ole32.lib advapi32.lib activeds.lib oleaut32.lib uuid.lib msvcrt.lib wldap32.lib wsock32.lib
del *.obj
MailExpiredAccounts.c
// Benutzeraccountablauf mailen, letzte Änderung 06.03.08 ,author: borwinius
#include <stdio.h>
#include <windows.h>
#include <winsock2.h>
#include <windowsx.h>
#include <commctrl.h>
#include <tchar.h>
#include <wchar.h>
#include <string.h>
#include <shellapi.h>
#include <shlobj.h>
#include <activeds.h>
#include <adsiid.h>
#include <time.h>
#include <math.h>
#include <rpc.h>
#include <winldap.h>
 
void MySnd(char *, char *, char *, char *); //Mail per SMTP senden
 
#define laenge 255
 
// TCHAR szComputerName[laenge];
TCHAR szStr[1024], szStrRcv[1024 * 1024], szResult[1024 * 50];
char buf2[laenge]= "Dies ist eine automatisch generierte Email !\n\nBitte pruefen Sie die Richtigkeit.\n\n";
double tage = 0;
 
TCHAR szSender[laenge] = "absender@dom.ain";
TCHAR szXmailer[laenge] = "automatischer Mailer copyright absender@dom.ain";
TCHAR lpszTo[laenge] = "empfaenger@dom.ain";
TCHAR lpszServer[laenge] = "smtpsrvoderIPaddresse";
//------------------------------------------------------------------
int main(void)
{
 
    IADs *pADs;
    IADsContainer * pCont;
    IADsUser *pADsUser;
    BSTR bstr;
    HRESULT hr;
    VARIANT vChild, var;
    DATE date;
    SYSTEMTIME st;
    double dSt;
    int i = 0;
    int pw ; // Passwort läuft nicht ab(1)
    char buf[255];
 
    GetLocalTime(&st); // Systemzeit ermitteln
    SystemTimeToVariantTime(&st,&dSt); // Zeit für Berechnung umwandeln
 
    // Initialize COM before calling any ADSI functions or interfaces.
    hr = CoInitialize(NULL);
    if (hr != S_OK) { return 0; }
    //hier die eigene NT-Domäne eintragen
    hr = ADsGetObject( L"WinNT://myNTDomain", &IID_IADsContainer, (void**) &pCont);
 
    if( hr==S_OK)
    {
     IEnumVARIANT * pEnum;
     ADsBuildEnumerator (pCont,&pEnum);
     while((hr = ADsEnumerateNext (pEnum, 1, &vChild, NULL)) == S_OK)
     {
       if(hr!=S_OK) break;
       hr = vChild.pdispVal->QueryInterface (&IID_IADsUser,(void**)&pADsUser);
       VariantClear(&vChild);
       if (hr!=S_OK) break;
       hr = pADsUser->Get(L"UserFlags",&var);
       pw = 0;// Passwort läuft ab
 
       if ((V_I4(&var) & ADS_UF_DONT_EXPIRE_PASSWD) > 0)
       pw = 1;
       VariantClear(&var);
       if(hr!=S_OK) break;
         hr = pADsUser->QueryInterface(&IID_IADs, (void**) &pADs);
         if(hr!=S_OK) break;
          if( S_OK == pADs->get_Name(&bstr) )
           {
            //--------------------------------------------------
	    // hier wird das Passwortablaufdatum ausgelesen
	    hr = pADsUser->get_AccountExpirationDate(&date);
	    // VARIANT var;
	     if (SUCCEEDED(hr))
		{
        	 VARIANT varz;
		 varz.vt = VT_DATE;
                 varz.date = date;
                 tage = (date - dSt);
		//---------------------------------Alle ablaufenden Konten mit weniger 30 Tagen
		if ( (tage < 30) && (tage > -1) ) 
		   {
		    i++;
                    wsprintf(buf,"Der Domaenenaccount von %S laeuft in %d Tagen ab. \n",bstr,(int) tage);
	            strcat(buf2,buf);
                   }
		//----------------------------------
		VariantClear(&varz);
		}
           //--------------------------------------------------
}
//--------------------------------------------------
        pADsUser->Release();
        pADs->Release();
    }
    SysFreeString(bstr);
    ADsFreeEnumerator(pEnum);
    pCont->Release();
   }
  CoUninitialize();
// wenn keine Einträge vorhanden sind soll das Programm ohne mail beendet werden.
if(!i) { return 0; }
 
  MySnd(lpszServer,"personalverwaltung@dom.ain", "Domaenenaccountablauf", buf2); // Email senden
  MySnd(lpszServer,"Hausnetz@dom.ain", "Domaenenaccountablauf", buf2); // Email an hausnetz senden
//  MySnd(lpszServer,"dritteAdresse@dom.ain", "Domaenenaccountablauf", buf2); // Email an weitere senden
 
  return 1;
}
//-------------------------------------------------------------
//Funktion zum Mailversenden über SMTP
void MySnd(char *lpszServer , char *lpszTo, char *lpszSubject, char *lpszMail)
{
    WSADATA wsaData;
    LPHOSTENT lpHost;
    LPSERVENT lpServ;
    SOCKET s;
    int iProtocolPort;
    SOCKADDR_IN sockadd;
    char *seps = "\r", *token;
 
    if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
        printf("WSAStartup \tError\n");
        return;
    }
    if (strcmp(lpszServer, "") == 0) {
        printf("kein szServerName ? \tFehler\n");
        return ;
    }
    lpHost = gethostbyname(lpszServer);
    if (lpHost == NULL) {
        printf("%s existiert nicht oder kann nicht aufgelöst werden", lpszServer);
        return;
    }
    s = socket(PF_INET, SOCK_STREAM, 0);
    if (s == INVALID_SOCKET) {
        printf("INVALID_SOCKET \tError\n");
        return;
    }
    lpServ = getservbyname("mail", NULL); // SMTPPort  ermitteln
    if (lpServ == NULL) {
        printf("getservbyname\n");
        iProtocolPort = htons(IPPORT_SMTP);
    } else {
        iProtocolPort = lpServ->s_port;
    }
    sockadd.sin_family = AF_INET;
    sockadd.sin_port = iProtocolPort;
    sockadd.sin_addr = *((LPIN_ADDR)*lpHost->h_addr_list);
    if (connect(s, (PSOCKADDR)&sockadd, sizeof(sockadd))) {
        printf("Socket connect \tError\n");
        return;
    }
    memset(szStrRcv, '\0', sizeof(szStrRcv));
    recv(s, szStrRcv, sizeof(szStrRcv), 0);
//    printf("%s\n",szStrRcv);
 
    strcpy(szStr,  "HELO ");				//Verbindung mit Server herstellen
    strcat(szStr, lpszServer);
    strcat(szStr, "\r\n");
    send(s, szStr, strlen(szStr), 0);
    memset(szStrRcv, '\0', sizeof(szStrRcv));
    recv(s, szStrRcv, sizeof(szStrRcv), 0);
//    printf("%s\n",szStrRcv);
 
    if (strcmp(szSender, "") == 0) {
        printf("kein Absender ?\tFehler\n", MB_OK);
        return ;
    }
    wsprintf(szStr, "MAIL FROM: <%s>\r\n", szSender); // Absender angeben
    send(s, szStr, strlen(szStr), 0);
    memset(szStrRcv, '\0', sizeof(szStrRcv));
    recv(s, szStrRcv, sizeof(szStrRcv), 0);
//    printf("%s\n",szStrRcv);
 
    wsprintf(szStr, "RCPT TO:<%s>\r\n", lpszTo); // Empfänger angeben
    send(s, szStr, strlen(szStr), 0);
    memset(szStrRcv, '\0', sizeof(szStrRcv));
    recv(s, szStrRcv, sizeof(szStrRcv), 0);
//    printf("%s\n",lpszTo);//szStrRcv);
 
/*    wsprintf(szStr, "RCPT TO:CC-Empfaenger@dom.ain>\r\n"); // Empfänger 2 angeben
    send(s, szStr, strlen(szStr), 0);
    memset(szStrRcv, '\0', sizeof(szStrRcv));
    recv(s, szStrRcv, sizeof(szStrRcv), 0);
  printf("%s\n",szStrRcv);
*/
    strcpy(szStr, "DATA\r\n");					//Daten übergeben
    send(s, szStr, strlen(szStr), 0);
    memset(szStrRcv, '\0', sizeof(szStrRcv));
    recv(s, szStrRcv, sizeof(szStrRcv), 0);
//    printf("%s\n",szStrRcv);
 
	strcpy(szStr, "X-Mailer: ");
    lstrcat(szStr,szXmailer);lstrcat(szStr,"\r\n");
	send(s, szStr, strlen(szStr), 0);
 
	strcpy(szStr, "From: ");
    lstrcat(szStr,szSender);lstrcat(szStr,"\r\n");
	send(s, szStr, strlen(szStr), 0);
 
	strcpy(szStr, "To: ");
    lstrcat(szStr,lpszTo);lstrcat(szStr,"\r\n");
	send(s, szStr, strlen(szStr), 0);
 
    wsprintf(szStr, "Subject: %s \r\n", lpszSubject); // Betreff
    send(s, szStr, strlen(szStr), 0);
    strcpy(szStr, "\r\n");
    send(s, szStr, strlen(szStr), 0);
 
    token = strtok(lpszMail, seps);
 
    while (token != NULL) {
        if (token[0] == '\n') {
            strcpy(szStr, token + 1);
        } else {
            strcpy(szStr, token);
        }
        strcat(szStr, "\r\n");
        send(s, szStr, strlen(szStr), 0);
        token = strtok(NULL, seps);
    }
    strcpy(szStr, ".\r\n");							// Ende der Daten
    send(s, szStr, strlen(szStr), 0);
    memset(szStrRcv, '\0', sizeof(szStrRcv));
    recv(s, szStrRcv, sizeof(szStrRcv), 0);
//    printf("%s\n",szStrRcv);
 
    strcpy(szStr,  "QUIT\r\n");						// Ende der Verbindung
    send(s, szStr, strlen(szStr), 0);
    memset(szStrRcv, '\0', sizeof(szStrRcv));
    recv(s, szStrRcv, sizeof(szStrRcv), 0);
//    printf("%s\n",szStrRcv);
    closesocket(s);
    WSACleanup();
//    printf("keine Verbindung mehr \n");
    return;
}
//-----------------------------------------------------------------

Die Variablen im C-Code einschließlich „myNTDomain“ müssen angepasst werden.
Anschließend wird die compile.bat doppelt angeklickt oder in der Kommandozeile aufgerufen.
Sie erstellt eine Datei MailAccountExpirationsDate.exe
Diese wird auf einen Domänencontroller kopiert und per geplantem Task jeden Montag um 7Uhr gestartet.
Zur Sicherheit erhält der Hausnetzadmin auch noch die gleiche Mail.