Avatar billede Slettet bruger
27. august 2003 - 13:01 Der er 34 kommentarer og
1 løsning

"Maximum execution time"-error ved afsendelse af email med Zend

Jeg afsender emails ved brug af http://www.zend.com/codex.php?id=347&single=1 , adresserne hentes fra database (ca. 2000 stk.) men jeg får efter 30 sek. fejlen: Fatal error: Maximum execution time of 30 seconds exceeded . Det kører hos Wannafinds server og de kan ikke ændre de 30 sek. . Hvad gør jeg?
Avatar billede tipsen Nybegynder
27. august 2003 - 13:10 #1
Du sender dine email i mindre portioner - evt. 500 af gangen...
Avatar billede algizoft Nybegynder
27. august 2003 - 13:11 #2
Hvis php ikke kører i safe_mode kan du prøve:
set_time_limit(0);
Fjerner 30 sek. grænsen.

Hvis du ikke har lov til at køre denne funktion er du nødt til at dele dine email-adresser op.
Du kan f.eks. kalde dit sende-script i et antal iframes, hvor der ved hvert kald f.eks. sendes 500 emails.
Avatar billede Slettet bruger
27. august 2003 - 13:14 #3
Jeg bruger flg. kode (udpluk):
// Etablerer forbindelse til databasen via filen dbconnect.php
include('connect/dbconnect.php');

// Data hentes fra database
$res = mysql_query("SELECT email FROM tbl_customer") or die (mysql_error());

$from = "Kontor@fuglebjerggaard.dk"; //din egen mail :-)
$header = "Content-type: text/html; charset=iso-8859-1";
$subject = "Nyhedsbrev fra Fuglebjerggaard $date";
$body = "<html>
<head>
</head>...
...
</html>";

$smtp = new smtp_client;
$smtp -> smtp_client();

while (list($email, $email) = mysql_fetch_row($res)) {
  $smtp->email("$from", "$email", "$email", "$header", "$subject", "$body");
  }

$smtp->send();
mysql_close();

echo "Afsendelse af emails lykkedes!";
}

else {

echo "Afsendelse af emails lykkedes ikke!";
}
?>

Kan jeg få dig (tipsen) til at hjælpe mig lidt med loop'et?
Avatar billede Slettet bruger
27. august 2003 - 13:14 #4
>algizoft Jeg har ikke mulighed for at fjerne grænsen på 30 sek.
Avatar billede je79ayps Novice
27. august 2003 - 14:24 #5
Jeg ved ikke om du kan bruge: ini_set(max_execution_time,600);
Avatar billede Slettet bruger
27. august 2003 - 14:26 #6
hvor bruger jeg den?
Avatar billede tipsen Nybegynder
27. august 2003 - 14:31 #7
Det er stadig en "grim" løsning da scriptet køres på et webhotel som deles med mange andre - det er hård belastning af serveren i lang tid - det bør man (synes jeg) ikke gøre...
Avatar billede Slettet bruger
27. august 2003 - 14:34 #8
Men hvad gør jeg så? Jeg skal altså sende en ca. 500 afsted ad gangen, men hvordan?
Avatar billede tipsen Nybegynder
27. august 2003 - 15:36 #9
Jeg vil foreslå, at du sætter et "flag" altså en parameter der kan være sand eller falsk og indikerer om der er udsendt email til personen eller ej.

Og så gør du noget i retning af:

SELECT * FROM tabel WHERE NOT emailsent ORDER BY id ASC LIMIT 0, 200
loop over de valgte poster {
blablaba email...
}
UPDATE tabel SET emailsent=true WHERE NOT emailsent ORDER BY id ASC LIMIT 0, 200

-den kører du så nogle gange til alle personer har fået sendt emails

Inden du sætter scriptet i gang næste gang, skal du så lige sørge for at nulstille emailsent kolonnen!
Avatar billede Slettet bruger
28. august 2003 - 10:27 #10
Jeg har fået flg. til at virke, dog bliver den ved med at sende mails idet den sidste sql ikke virker (sætter ikke 'ok' ind!) Nogen idé om hvorfor?

...
$res = mysql_query("SELECT email FROM tbl_customer_tmp WHERE emailsent <> 'ok' ORDER BY id ASC LIMIT 0, 2") or die (mysql_error());

$smtp = new smtp_client;
$smtp -> smtp_client();

while (list($email, $email) = mysql_fetch_row($res)) {
  $smtp->email("$from", "$email", "$email", "$header", "$subject", "$body");
  }

$smtp->send();

$sql="UPDATE tbl_customer_tmp SET emailsent = 'ok' WHERE emailsent <> 'ok' ORDER BY id ASC LIMIT 0, 2";

$result=mysql_query($sql);

header("Location:sammeside.php");

...
Avatar billede tipsen Nybegynder
28. august 2003 - 11:30 #11
rettelser:

$res = mysql_query("SELECT email FROM tbl_customer_tmp WHERE emailsent <> 'ok' ORDER BY id ASC LIMIT 0, 2") or die (mysql_error());

$smtp = new smtp_client;
$smtp -> smtp_client();

while (list($email) = mysql_fetch_row($res)) {
  $smtp->email($from, $email, $email, $header, $subject, $body);
}
$smtp->send();

$sql="UPDATE tbl_customer_tmp SET emailsent = 'ok' WHERE emailsent <> 'ok' ORDER BY id ASC LIMIT 0, 2";
$result = mysql_query($sql) or die (mysql_error());
//indsæt pause/wait på 10-15 sekunder, så serveren ikke belastes hårdt og vedvarende - giv lidt til andre processer.
header("Location:sammeside.php");
Avatar billede Slettet bruger
28. august 2003 - 11:41 #12
God idé med et wait! Den bliver ved med at brokke sig over ORDER BY id ASC i den sidste sql. Skal det med? eller kan jeg bare skrive $sql="UPDATE tbl_customer_tmp SET emailsent = 'ok' WHERE emailsent <> 'ok' LIMIT 2"; fordi det virker nemlig (jeg ved bare ikke om det er helt korrekt!?)
Avatar billede Slettet bruger
28. august 2003 - 11:57 #13
Dette er min kode nu - den udskriver dog "Det var det!" uden at sende nogle emails:

$res = mysql_query("SELECT email FROM tbl_customer_tmp WHERE emailsent <> 'ok' ORDER BY id ASC LIMIT 0, 2") or die (mysql_error());

$mysql_result=mysql_query($res);

$num_rows=@mysql_num_rows($mysql_result);
if ( $num_rows == 0 ) {

echo "Det var det!";
exit;
} else {

$smtp = new smtp_client;
$smtp -> smtp_client();

while (list($email, $email) = mysql_fetch_row($res)) {
  $smtp->email("$from", "$email", "$email", "$header", "$subject", "$body");
  }

$smtp->send();

$res2 = mysql_query("UPDATE tbl_customer_tmp SET emailsent = 'ok' WHERE emailsent <> 'ok' LIMIT 2") or die (mysql_error());

flush();
sleep(5);

header("Location:sammeside.php");
}

Og så lige en tak til jer der de sidste to dage har villet hjælpe - det er bare fedt!

jeg har altså to problemer: sidste sql der skal opdatere med ok og delen der skal afslutte det hele når alle emails er sendt.
Avatar billede tipsen Nybegynder
28. august 2003 - 12:31 #14
Alternativ (Du har ikke fået alle rettelser med fra sidste alternativ - de kommer her igen):

$numemails = 100;
$limitid = isset($_GET['limitid']) ? $_GET['limitid'] : $numemails;
$res = mysql_query("SELECT email FROM tbl_customer_tmp WHERE emailsent <> 'ok' AND id < $limitid") or die (mysql_error());
if (mysql_num_rows($res) > 0) {
  $smtp = new smtp_client;
  $smtp -> smtp_client();
  while (list($email) = mysql_fetch_row($res)) {
    $smtp->email($from, $email, $email, $header, $subject, $body);
  }
  $smtp->send();
  $sql="UPDATE tbl_customer_tmp SET emailsent = 'ok' WHERE emailsent != 'ok' AND id < $limitid";
  $res = mysql_query($sql) or die (mysql_error());
  //indsæt pause/wait på 10-15 sekunder, så serveren ikke belastes hårdt og vedvarende - giv lidt plads til andre processer.
  header("Location:sammeside.php?" . ($limitid + $numemails));
  exit;
} else {
  echo "Jeg tror jeg er færdig for denne gang...";
  exit;
}

Det vil forøvrigt være hurtigere, hvis emailsent er en tinyint-kolonne og du benytter 0 og 1 til at angive sandt/falsk - dermed kan du bare skrive "WHERE NOT emailsent" i din query - det er hurtigere!
Avatar billede Slettet bruger
28. august 2003 - 12:33 #15
Det ser jo fornemt ud - jeg prøver det lige!
Avatar billede Slettet bruger
28. august 2003 - 12:40 #16
Den sender kun af een omgang og stopper!?
Avatar billede tipsen Nybegynder
28. august 2003 - 12:56 #17
Skriver den så: Jeg tror jeg er færdig for denne gang... ?
Avatar billede Slettet bruger
28. august 2003 - 13:02 #18
ja det skriver den nemlig
Avatar billede Slettet bruger
28. august 2003 - 13:05 #19
Nye kode der giver ovenståande fejl:

$numemails = 10;
$limitid = isset($_GET['limitid']) ? $_GET['limitid'] : $numemails;
$res = mysql_query("SELECT email FROM tbl_customer_tmp WHERE emailsent <> 'ok' AND id < $limitid") or die (mysql_error());
if (mysql_num_rows($res) > 0) {
  $smtp = new smtp_client;
  $smtp -> smtp_client();
  while (list($email) = mysql_fetch_row($res)) {
    $smtp->email($from, $email, $email, $header, $subject, $body);
  }
  $smtp->send();
  $sql="UPDATE tbl_customer_tmp SET emailsent = 'ok' WHERE emailsent != 'ok' AND id < $limitid";
  $res = mysql_query($sql) or die (mysql_error());
  //indsæt pause
  flush();
  sleep(5);
 
  header("Location:sammeside.php?" . ($limitid + $numemails));
  exit;
} else {
  echo "Jeg tror jeg er færdig for denne gang...";
  exit;
}

Gamle kode der virker efter to test (med ca. 100 emails):

$res = mysql_query("SELECT email FROM tbl_customer_tmp WHERE emailsent <> 'ok' ORDER BY id ASC LIMIT 0, 2") or die (mysql_error());

// Benytter @ til at deaktivere PHP-fejl
$num_rows=@mysql_num_rows($res);
if ( $num_rows == 0 ) {

echo "Det var det!";
exit;
} else {

$smtp = new smtp_client;
$smtp -> smtp_client();

while (list($email, $email) = mysql_fetch_row($res)) {
  $smtp->email("$from", "$email", "$email", "$header", "$subject", "$body");
  }

$smtp->send();

$res2 = mysql_query("UPDATE tbl_customer_tmp SET emailsent = 'ok' WHERE emailsent <> 'ok' LIMIT 2") or die (mysql_error());

flush();
sleep(5);

header("Location:sammeside.php");
}
Avatar billede Slettet bruger
28. august 2003 - 13:12 #20
Er ? i $limitid = ... rigtigt, skal det ikke være +
Avatar billede tipsen Nybegynder
28. august 2003 - 13:18 #21
Det er fordi du ikke bruger mit alternativ... - i stedet for at smide mine rettelser ind i din kode så prøv at smid din kode ind i mit alternativ :-) (Find 5 fejl ;-))
Avatar billede tipsen Nybegynder
28. august 2003 - 13:19 #22
Bare sammenlign din og min udgave og find de ting du har glemt/overset.
Avatar billede Slettet bruger
28. august 2003 - 13:24 #23
Jeg kan f... ikke se det!?
Avatar billede Slettet bruger
28. august 2003 - 13:25 #24
er det limitid der skal være lig med det antal der skal sendes pr gang?
Avatar billede Slettet bruger
28. august 2003 - 13:32 #25
Jeg giver snart op - Jeg kan ikke se hvad det er fra min kode som jeg skal sætte ind i din!?
Avatar billede Slettet bruger
28. august 2003 - 13:33 #26
Men kan du ikke så give fortælle mig om min kode kan bruges i stedet for dit alternativ - for så må jeg nøjes med en (det virkede nemlig umiddelbart fint)
Avatar billede tipsen Nybegynder
28. august 2003 - 14:09 #27
I den nye kode fra "Kommentar: jlyngso 28/08-2003 13:05:17" skal header-linien rettes til:

header("Location:sammeside.php?limitid=" . ($limitid + $numemails));
Avatar billede Slettet bruger
28. august 2003 - 14:20 #28
Du er bare super! Det virker fint nu og jeg har også fået tilføjet den detalje som tømmer emailsent igen efter afsendelse af dem alle - Så meget stort tak skal du have!!! :-)
Avatar billede tipsen Nybegynder
28. august 2003 - 14:31 #29
husk min kommentar omkring tinyint = hurtigere kode!
Avatar billede tipsen Nybegynder
30. august 2003 - 10:10 #30
Jeg har modtaget mail fra jlyngso og indholdet følger her for evt. interesserede:

27. og 28. august hjalp du mig med at få php til at afsende emails til en stor mængde adresser ved
brug af Zend ( http://www.eksperten.dk/spm/393199 ). Vi endte op med at få det hele til at virke.

Jeg er dog ved afsendelse af emails'ne stødt på et lidt mærkeligt problem: Efter at have stået og
afsendt 10 emails ad gangen med 25 sek. pause afbrydes det hele efter ca. 3 min. med:
    Action canceled
      Internet Explorer was unable to link to the Web page you requested..


I starten afsendte jeg 50 emails med 5 sek. pause og derefter 25 emails med 10 sek. pause, men begge
gange afbrød den efter et par minutter med "Fatal error: Maximum execution time of 30 seconds
exceeded...". Jeg kontaktede webhotellet (Wannafind) og efter deres anbefaling ændrede jeg antal
emails og pause til ovenstående (10 emails / 25 sek. ), men fik altså efter nogle minutter (i
databasen kan jeg se at den nåede til ca. nummer 400) ovenstående fejl. Det virker på mig helt
utroligt hvis Wannafinds smtp-server ikke skal kunne sende 10 emails afsted ad gangen!?

1. Du har en grænse på 30 sek. for hvor lang tid et script må tage at eksekvere - de 30 sek. dækker både den pause du sætter ind samt tiden for at udføre div. kode - blandt andet afsendelse af x antal emails!
2. Du har en grænse derhjemme på din Internet Explorer der ikke tror at skidtet fungerer fordi det tager så lang tid at hente og der kommer ikke noget output.

Jo længere pause du indsætter jo bedre for serveren men desto dårligere for IE - dvs. der skal så vidt muligt findes en kompromis løsning som tilfredsstiller begge kriterier!

Jeg vil foreslå dig følgende kombinationer:

1. 20 mails 5 sek
2. 40 mails 5 sek
3. 50 mails 5 sek
4. 100 mails 5 sek
5. 100 mails 10 sek
6. 200 mails 10 sek

Det bør ikke tage lang tid at afsende disse mails og jeg tvivler på, at det er SMTP serveren der giver problemer.

Derudover tager det noget tid at koble op til mysql-basen og eksekvere dine mysql-statements, så det kan ikke betale sig at sende for små mængder post af gangen!

Jeg vil gerne have respons på pkt. 1-6 ovenfor og høre om resultaterne - både mht. opfyldelse af pkt. 1 og pkt. 2!
Avatar billede Slettet bruger
30. august 2003 - 12:32 #31
Tak for hjælpen!

Jeg har med succes afsendt 900 emails (til mig selv som test) med både kombination 5. og 6.. Da der endes op med at skulle afsendes over 2000 emails tror jeg at kombination 6. vil være at foretrække.

Er det ikke muligt at udskrive f.eks. teksten "Emails afsendes!" hver gang siden loades, for på den måde at undgå at IE kommer med "Kan ikke finde siden..."?
Avatar billede tipsen Nybegynder
30. august 2003 - 12:48 #32
så kan du ikke lave header() - det kan ikke kombineres med html-output!

Men du kan måske lave et eller andet redirect efter x antal sekunder - altså i stedet for pausen... - det kan stensikkert laves som meta-tag, men jeg mener også jeg har set det i et alm. php header-kald

(eks: <meta http-equiv="refresh" content="10;url=http://www.washingtonscholarshipfund.org">)
Avatar billede tipsen Nybegynder
30. august 2003 - 12:50 #33
Avatar billede tipsen Nybegynder
30. august 2003 - 12:51 #34
Med method II kan du sagtens lave output til browseren - bare du placerer header-kaldet inden dit output!

Eksempelvis:

Email 1-500 sendt med succes!
-Fortsætter om 10 sekunder med næste batch!

(dvs. skrot dit sleep() kald!)
Avatar billede Slettet bruger
30. august 2003 - 13:27 #35
Flg. virker perfekt:

header( 'refresh: 10; url=sammeside.php?limitid=' . ($limitid + $numemails));
echo '200 emails afsendt - Sender næste 200 om 10 sekunder...';

Nu er problemet vist løst - også selvom der skal afsendes mange flere emails...
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester