Emaile - różna treść, adresy jednocześnie

0

Witam
Po burzliwej i deszczowej nocy spędzonej przy kompie, lekko rozkładam ręce. Otóż napisałem kod który pozwala mi wysyłać emaile na podane przeze mnie adresy ale z jednakową treścią z komponentu Richedit. OK działa, jednak zorientowałem się wieczorem, ze nie na tym rzecz polega.
Rzecz polega na tym, aby wysyłać pod różne adresy, różne wiadomości jednocześnie.

Tak jak wspominałem we wcześniejszych postach, musze napisać program który będzie wysyłał raporty o różnej treści do różnych pracowników ze swoimi adresami.

Jak wygląda sytuacja w moim programie:

Mam tabelę DBGrid, która mi wyświetla rekordy z IBX-owych komponentów, nauczyłem się zapytań SQL. Pomimo, że nie jestem programista i pewnie nigdy nie zostanę, tylko zwykłym kurierem, podoba mi się to. Uzywam bazę Firebird na podstawie tutejszych postów.

Tabela:
| ID_prac | Nazwisko | Imie | Email | Raport |

| 1 | Kowalski | Jan | [email protected] | 35 przesyłek wysłanych |
| 2 | Nowak | Paweł | [email protected] | 14 na jutro do wysyłki |
itd.
itd.

Rekordów będzie sporo, nawet kilkaset, ale danym dniu może być tylko kilkadziesiąt. Teraz o co chodzi?

Chodzi o to aby za pomocą Buttona, w której mam procedure wysyłania emaila przez idSMTP i idMessage wysłac jednocześnie do tych pracowników pod ich adresy odpowiednie ich raporty.

Męczyłem to całą noc, a teraz ledwo widzę, bo mi się oczy kleją i nie potrafię tego zrobić. Próbowałem coś z pętlą Repeat...Until, ale nic nie idzie.

Proszę Was, jak to zrobić, aby poniższy kod wysyłał emaile z tymi raportami do odpowiednich osób za pomocą poniższego kodu? Ja już nie daję rady. Siedze teraz na urlopie specjalnei do jutra. Szef mi dał wolne na napisanie tego programu i tylko to mi już zzostało. Pomocy. [browar]

Kod do wysyłania poczty:

procedure TForm1.Button1Click(Sender: TObject);
var
 j:integer;
begin
 try
  idMessage1.CharSet:='charset="windows-1250"';  //ustawiamy kodowanie
  idMessage1.ContentTransferEncoding:='8bit';  // przesyłanie 8bitowe
  idMessage1.ContentType:='text/html';  // przesyłamy tekst
  idMessage1.Body:=Richedit1.Lines;  // treść maila

  // ustawienia wiadomości
  idMessage1.From.Address := 'xxx'; // od kogo
  idMessage1.From.name := 'Oskar';
  idMessage1.Subject := Edit1.Text;
  idMessage1.Recipients.EMailAddresses :=Edit2.Text;

  // weryfikacja
  idSMTP1.UserName := 'xxx';
  idSMTP1.Password := 'xxx';
  idSMTP1.Host := 'xxx';

  //wpisz gdy serwer nie wymaga uwierzytelnienia
  idSMTP1.AuthenticationType:=atNone;

  //wpisz gdy serwer wymaga uwierzytelnienia (zalecane)
  idSMTP1.AuthenticationType:=atLogin;

  idSMTP1.Connect;
  idSMTP1.Send(idMessage1);
  idSMTP1.Disconnect;

   // ShowMessage('Mail został wysłany');
 except
  Application.MessageBox('Trwa wysyłanie raportów. Poczekaj chwilkę...','Raport dzienny',
  MB_IconError or MB_OK);
end;
end;
0

Ja to robię mniej więcej tak (starałem sie to przerobić pod twój kod):

  idMessage1.CharSet:='charset="windows-1250"';  //ustawiamy kodowanie
  idMessage1.ContentTransferEncoding:='8bit';  // przesyłanie 8bitowe
  idMessage1.ContentType:='text/html';  // przesyłamy tekst

  nazwa_tabeli.first;
  while not nazwa_tabeli.eof do
  begin
          idMessage1.clear; //CZYŚCIMY

          idMessage1.from.name := 'Oskar'; //NAZWA NADAWCY
          idMessage1.from.address := 'oskar@firma_kurierska.pl'; //ADRES NADAWCY
          idMessage1.subject:=Edit1.Text; //TEMAT MAILA
          idMessage1.recipients.EMailAddresses:=nazwa_tabeli['Email']; //ADRESAT MAILA

	  idSMTP1.UserName := 'xxx'; //DANE DO POŁACZENIA Z SERWEREM POCZTOWYM (TUTAJ JA MAM ADRES IP)
	  idSMTP1.Host := 'xxx';
	  idSMTP1.Password := 'xxx';
	  idSMTP1.AuthenticationType:=atLogin;

          idmessage1.Body.Add(nazwa_tabeli['Raport']); //TREŚĆ MAILA

          try
            begin
              idSMTP1.connect;
              idSMTP1.Send(idmessage1);
            end;
            finally
              idSMTP1.disconnect;
          end;

          nazwa_tabeli.Next;
  end;
0

Przed while warto by dać jeszcze

nazwa_tabeli.First;
0
pytek napisał(a)

Przed while warto by dać jeszcze

nazwa_tabeli.First;

Tak się składa, że w tym samym momencie to samo mi się przypomniało i edytowałem mój post :)

Poza tym zastanawiam się tak teraz, czy poza pętlę nie wyciągnąć to, co jest i tak zawsze stałe:

  idMessage1.CharSet:='charset="windows-1250"';  //ustawiamy kodowanie
  idMessage1.ContentTransferEncoding:='8bit';  // przesyłanie 8bitowe
  idMessage1.ContentType:='text/html';  // przesyłamy tekst

  idMessage1.from.name := 'Oskar'; //NAZWA NADAWCY
  idMessage1.from.address := 'oskar@firma_kurierska.pl'; //ADRES NADAWCY
  idMessage1.subject:=Edit1.Text; //TEMAT MAILA

  idSMTP1.UserName := 'xxx'; //DANE DO POŁACZENIA Z SERWEREM POCZTOWYM (TUTAJ JA MAM ADRES IP)
  idSMTP1.Host := 'xxx';
  idSMTP1.Password := 'xxx';
  idSMTP1.AuthenticationType:=atLogin;

  nazwa_tabeli.first;
  while not nazwa_tabeli.eof do
  begin
//          idMessage1.clear; //CZYŚCIMY
          idMessage1.recipients.EMailAddresses:=nazwa_tabeli['Email']; //ADRESAT MAILA
          idmessage1.Body.Clear;
          idmessage1.Body.Add(nazwa_tabeli['Raport']); //TREŚĆ MAILA

          try
            begin
              idSMTP1.connect;
              idSMTP1.Send(idmessage1);
            end;
            finally
              idSMTP1.disconnect;
          end;

          nazwa_tabeli.Next;
  end;

Podejrzewam, że też będzie działało, choć nie próbowałem.

Tylko, że wtedy nie można za każdym razem czyścić idMessage1:

//          idMessage1.clear; //CZYŚCIMY

Ale za to trzeba czyścić treść maila:

          idmessage1.Body.Clear;

Inna rzecz, że w tym moim pierwszym wpisie tutaj poza pętlą nieprawidłowo były te trzy pierwsze linijki, które ustawiały kodowanie itp., a potem te ustawienia były kasowane komendą idMessage1.clear;. Tak więc albo nie czyścimy idMessage1, albo za każdym razem po wyczyszczeniu wpisujemy wszystkie parametry od nowa. W tym pierwszym przypadku trzeba pamiętać aby za każdym razem czyścić treść maila, bo inaczej będą dodawane tylko nowe linijki i każdy kolejny mail będzie zawierał treść wszystkich poprzednich.

0

Cały czas wyskakuje błąd:


Debugger Exception Notification

Project Project1.exe raised exception class EIdProtocolReplyError with message 'Connection denied after dictionary attack
'. Process stopped. Use Step or Run to continue.

OK Help

I zaznacza linijkę:

   idSMTP1.Send(idmessage1);
0

A to nie czasem jaki antywirus blokuje "myśląc", że rozsyłasz jakiś spam? Komunikat błędu mówi o odmowie połączenia po ataku słownikowym więc myślę że to antywirus lub firewall.

0

Ano nie używam antywirusa. :) Próbuję dalej.

0

No chyba, że jest jeszcze inny sposób do wysyłania poczty z daną treścią? (Zaraz się zarejestruję, aby edytowac posty).
Firewall wyłączenie też nic nie dał.

0

Powyższy kod miałem dobrze jeśli chodzi o autentykację. Dodałem z powrotem tą linijkę i teraz już wszystko działa. :)
Wysyła emaile do pracowników z ich treścią.
Jednak mam pytanie jeszcze jedno:

Jak program będzie się zachowywał, gdy będzie trzeba wysłać np. 100 listów na raz? Słyszałem o wątkach, że mogą odwiesić jakoś program. jednak to mnie przerasta ten kod.

0

A zwykły sposób bez pętli (jeden email) Ci działał bo jeżeli tak to można wykluczyć nieprawidłową konfigurację.

EDIT// Już odpowiedziałeś

co do wysyłania wiecej niz 1 jak 1 nie zamula to zwyłe

idSMTP1.Send(idmessage1);
Application.ProcessMessages; //to dodaj

powinno załatwić sprawę a jak nie to rzeczywiście będzie trzeba wysyłać w wątku.

0

A spróbuję później czy tak działa. :) Jednak chyba nie bo IBQuery to trzeba tym EOF'em lecieć niezależnie ile ma rekordów.
Tak mi się wydaje. :)

0
Oska_kurier napisał(a)

Powyższy kod miałem dobrze jeśli chodzi o autentykację. Dodałem z powrotem tą linijkę i teraz już wszystko działa. :)

Którą "tą" linijkę?

Oska_kurier napisał(a)

Jak program będzie się zachowywał, gdy będzie trzeba wysłać np. 100 listów na raz? Słyszałem o wątkach, że mogą odwiesić jakoś program. jednak to mnie przerasta ten kod.

Ja wysyłam nieraz po kilka tysięcy maili. Żeby nie zapchać sobie programu pocztowego na serwerze, to robię to na raty. Np. co parę minut wysyłam po 100 maili. Poza tym trzeba mieć odpowiednio skonfigurowany program pocztowy na serwerze, żeby np. nie miał czegoś takiego, że może wysłać tylko 1 maila na minutę, bo wtedy to sobie zapchasz kolejkę na parę dni :P

A robię to w ten sposób, że zliczam liczbę wykonanych pętli:

i:=i+1;

a następnie na końcu pętli daję warunek:

if i=100 then exit;

Program po 100 wysłanych mailach się zatrzyma i dopóki go nie uruchomisz od nowa, to nie będzie wysyłał maili.

Tylko, że w tym przypadku trzeba usunąć linię:

nazwa_tabeli.First;

żeby za każdym razem nie zaczynał od początku wysyłać maili, tylko w miejscu, gdzie się zatrzymał.

0

Chciałem Wam bardzo podziękować za pomoc. :)
Wiem, że są tu dobrzy koderzy zjaący się na rzeczy.
Na jutro musze oddać programik i jeszcze go dziś będe testował. :)
Została jeszcze kosmetyka.

Kurde ze mną to tak, jak z baletnicą. Dać jej auto do naprawienia. :)
Tak samo kurier do programowania się wziął. Coś czuję, że się tego pouczę. :)

Jeszcze raz dziękuję. [browar]

Do Ozi.:
Oczywiście 100 to był przykład. :)
Chodziło mi o linijkę z autoryzacją loginu, która odziwo usunąłem sobie sam.

  //wpisz gdy serwer wymaga uwierzytelnienia (zalecane)

  idSMTP1.AuthenticationType:=atLogin;

Jeszcze jedno pytanie. Wiadomo pracujemy 8 - 12 godzin i nie raz komp jest uruchamiany w biurze i odpalany na nowo program. Co teraz zrobić jak wysłałem już w danym dniu raporty a one dalej istnieją do wysłania? Musiałbym zrobić jakąś nową ukrytą kolumnę i ją edytować np "+", gdzie plus to wysłane czy jak? Po prostu chodzi o to, aby raz w danym dniu (w danej dacie) te emaile szły, nie kilka razy, bo będzie smierdzieć spamem. :-)

0
Oskar_kurier napisał(a)

Chciałem Wam bardzo podziękować za pomoc. :)

Jak będziesz w Rybniku, to postawisz piwo :P

Odpowiedz na mojego poprzedniego posta.

0

Ozi:

Jak będziesz w Rybniku, to postawisz piwo :)

Mojego kumpla zona jest z rybnika, a brzydka jak noc. :)
Podobno tam macie najwięcej rond w Polsce? 24? :)

0
Oskar_kurier napisał(a)

Chodziło mi o linijkę z autoryzacją loginu, która odziwo usunąłem sobie sam.

 idSMTP1.AuthenticationType:=atLogin;

Aha, no bez tego, to raczej nie pociągnie, jeśli serwer wymaga uwierzytelnienia. Mój akurat nie wymaga, więc nawet nie wpisuję loginu i hasła.

Oskar_kurier napisał(a)

Jeszcze jedno pytanie. Wiadomo pracujemy 8 - 12 godzin i nie raz komp jest uruchamiany w biurze i odpalany na nowo program. Co teraz zrobić jak wysłałem już w danym dniu raporty a one dalej istnieją do wysłania? Musiałbym zrobić jakąś nową ukrytą kolumnę i ją edytować np "+", gdzie plus to wysłane czy jak? Po prostu chodzi o to, aby raz w danym dniu (w danej dacie) te emaile szły, nie kilka razy, bo będzie smierdzieć spamem. :-)

Dobrze kombinujesz. Też bym zrobił po każdym wysłaniu zaznaczenie, że mail już poszedł.
Dodaj do tabeli kolumnę o nazwie "Wyslane" np. typu char(1) - jeden znak. Jako standardową wartość tego pola daj np. "N", a po każdym wysłanym mailu wartość ta będzie zmieniana na "T". Przy okazji robisz IF-a, który sprawdza, że jak wartość jest "T", to nie wysyła maila, a jak nie jest "T", to wysyła.

  idMessage1.CharSet:='charset="windows-1250"';  //ustawiamy kodowanie
  idMessage1.ContentTransferEncoding:='8bit';  // przesyłanie 8bitowe
  idMessage1.ContentType:='text/html';  // przesyłamy tekst

  idMessage1.from.name := 'Oskar'; //NAZWA NADAWCY
  idMessage1.from.address := 'oskar@firma_kurierska.pl'; //ADRES NADAWCY
  idMessage1.subject:=Edit1.Text; //TEMAT MAILA

  idSMTP1.UserName := 'xxx'; //DANE DO POŁACZENIA Z SERWEREM POCZTOWYM (TUTAJ JA MAM ADRES IP)
  idSMTP1.Host := 'xxx';
  idSMTP1.Password := 'xxx';
  idSMTP1.AuthenticationType:=atLogin;

  nazwa_tabeli.first;
  while not nazwa_tabeli.eof do
  begin

        if nazwa_tabeli['Wyslany']<>'T' then
        begin

          idMessage1.recipients.EMailAddresses:=nazwa_tabeli['Email']; //ADRESAT MAILA
          idmessage1.Body.Clear;
          idmessage1.Body.Add(nazwa_tabeli['Raport']); //TREŚĆ MAILA

          try
            begin
              idSMTP1.connect;
              idSMTP1.Send(idmessage1);
              nazwa_tabeli.edit;
              nazwa_tabeli['Wyslany']:='T';
              nazwa_tabeli.post;
            end;
            finally
              idSMTP1.disconnect;
          end;

        end;
        nazwa_tabeli.Next;
  end;
Oskar_kurier napisał(a)

Mojego kumpla zona jest z rybnika, a brzydka jak noc. :)

Pewnie pochodzi z Wodzisławia ;-)

Oskar_kurier napisał(a)

Podobno tam macie najwięcej rond w Polsce? 24? :)

Tak jest. To prawdziwe wyzwanie dla kierowców, ale co to za problem dla zawodowego kuriera? :P
A na poważnie, to można się z tego faktu śmiać, ale ja jeżdżąc po innych miastach śmieję się z nich, że zamiast rond stawiają skrzyżowania ze światłami i robią sobie niepotrzebnie korki.

0

Ano z tymi IFami pomyślę. :) Jednak można jeszcze zrobić zapis do zmiennej wartości "wysłane" do jakiegoś pliku i zaszyfrować go. Niech sobie zapisuje po udanej wysyłce. :) Bez robienia dodatkowej kolumny. Jednak pojawia się problem: gdy wyślemy poczty, a dojdzie w ten sam dzień nowy rekord, to jakoś przydałoby się pofiltrować to, no i wracamy do punktu wyjścia, czyli nowa kolumna. :) Druga sprawa: ktoś może bawić się kalendarzem w windowsie i będzie lekkie zamieszanie. :)
P.S.
U mnie na wichurze są 3 ronda i jeździ mi się elegancko busem. :)
Nie, ona jest z Rybnika. :) Rond mi się podobają. Spoko się wtedy busem czy tirem manewruje. :)

0
Oskar_kurier napisał(a)

Ano z tymi IFami pomyślę. :) Jednak można jeszcze zrobić zapis do zmiennej wartości "wysłane" do jakiegoś pliku i zaszyfrować go. Niech sobie zapisuje po udanej wysyłce. :) Bez robienia dodatkowej kolumny.

Wg mnie robienie jakiegoś zaszyfrowanego pliku to nieporównywalnie dużo więcej roboty niż dodanie nowej kolumny do tabeli.

Oskar_kurier napisał(a)

Jednak pojawia się problem: gdy wyślemy poczty, a dojdzie w ten sam dzień nowy rekord, to jakoś przydałoby się pofiltrować to, no i wracamy do punktu wyjścia, czyli nowa kolumna. :) Druga sprawa: ktoś może bawić się kalendarzem w windowsie i będzie lekkie zamieszanie. :)

A co tu ma do tego data w Windowsie? Gdzie w kodzie sprawdza ci datę? Wysyłasz maile wtedy, gdy naciśniesz przycisk. A jak chcesz codziennie o tej samej porze, to sobie budzik w telefonie nastaw ;-)

Oskar_kurier napisał(a)

P.S.
U mnie na wichurze są 3 ronda i jeździ mi się elegancko busem. :)
Nie, ona jest z Rybnika. :) Rond mi się podobają. Spoko się wtedy busem czy tirem manewruje. :)

Już nie zagaduj, wisisz piwo i tyle ;-)
A laska może być z Rybnika, ale pewnie korzenie ma inne ;-) Rybniczanki, czy też dziewczyny z podrybnickich wiosek, są same fajne ;-)

0

Ozi:

A co tu ma do tego data w Windowsie? Gdzie w kodzie sprawdza ci datę? Wysyłasz maile wtedy, gdy naciśniesz przycisk. A jak chcesz codziennie o tej samej porze, to sobie budzik w telefonie nastaw

No właśnie i tu druga część programu. :) W tabeli mam jeszcze kolumnę Data_wys. Filtrowane są rekordy jeśli data w rekordach jest taka sama jak w danym dniu. :) Bo niezawsze będe wysyłał raporty w danym dniu, mogę to zrobić po weekendzie zamiast w piątek z piątkową datą. :) Dlatego ustawię wysyłkę na 25 sierpnia przykładowo i datę przestawię z dzisiaj właśnie na 25 to mi wyśle już dziś pocztę zamiast za 2 dni. :) Więc będę miał przekłamanie w pracy.
Zastanawiam się jak zablokowac to lub po prostu pobierać czas z neta. Mam nawet kodzik z serwerami. Połączenie netowe też mam w biurze. Ot takie coć.

Ozi:
[browar] x20 do Rybnika. Tylko musisz kuriera zawołać. :d
Dobra jak będę na Śląsku gdzieś tam to podjadę do Rybnika, to się od razu na ROW skoczy. :d

0

No to walcz z tym pobieraniem daty z serwera, bo to faktycznie chyba jedyny sposób, aby zapobiec błędom przy zmianie daty w Windowsie.

Na ROW serdecznie zapraszam :-) Ale bardziej na piłkę, niż na żużel ;-)

A kurierzy do naszej firmy jeżdżą codziennie po kilka razy. Zależy też z jakiej firmy kurierskiej :P

1 użytkowników online, w tym zalogowanych: 0, gości: 1