Swift Mailer tutorial

Swift Mailer is a fantastic library for sending email with php. Discuss this library or ask any questions about it here.

Moderators: Chris Corbyn, General Moderators

User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

At some point $_POST['marketsource'] was converted to a string directly from an array, thus resulting in the string "Array." Trace the variable backward to find the culprit.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

What feyd said ;) You're overwriting $_POST["marketsource"] somewhere.
JeffBell
Forum Newbie
Posts: 15
Joined: Thu Feb 01, 2007 8:17 am

Post by JeffBell »

Thank you both for the response. I scoured the code and simply do not see where it could be.

In the first 50 lines, it only appears once as seen below. (In fact, it only appears once in the entire script until the HTML dump/email body creation.)

Code: Select all

<?php

/** 1 **/
session_start();

/** 2 **/
//See if evil magic_quotes is enabled, and fix problems if it is
$quotes_on = (get_magic_quotes_gpc() || get_magic_quotes_runtime());
if ($quotes_on)
{
    foreach ($_POST as $key => $value)
    {
        $_POST[$key] = stripslashes($value);
    }
}

/** 3 **/
$_SESSION["post"] = $_POST;

/** 4 **/
//Load in the required Swift files
require_once "classes/Swift.php";
require_once "classes/Swift/Connection/SMTP.php";

/** 5 **/
//Create an empty array where we can catch any fields which were not filled in
$fields_not_set = array();

//FOR EACH REQUIRED FIELD
//Check if all POST data was sent, redirect with an error if not
if (empty($_POST["Name"])) $fields_not_set[] = "Name";
if (empty($_POST["Email"])) $fields_not_set[] = "Email";
//if (empty($_POST["subject"])) $fields_not_set[] = "subject";
//if (empty($_POST["comments"])) $fields_not_set[] = "comments";

//If $fields_not_set contains any values, then something wasn't filled in. Time to redirect.
if (!empty($fields_not_set))
{
    //Read further down to see how we'll modify form.php to handle the error
    header("Location: contact_us.php?error=incomplete&fields=" . implode(",", $fields_not_set));
    exit();
}

//Copy the POST data to standard globals
$name = $_POST["Name"];
$email = $_POST["Email"];
$address = $_POST["Addy"];
$citystatezip = $_POST["CSZ"];
$entitytype = $_POST["entitytype"];
//var_dump($_POST["marketsource"]);
$marketsource = implode(", ", $_POST['marketsource']);
If there is a conflict here, perhaps you can show me the error of my ways? Or, if not, perhaps you can point me elsewhere to look? Either way I appreciate the help learning.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

I'll give a hint:

Code: Select all

if ($quotes_on) 
{ 
    foreach ($_POST as $key => $value) 
    { 
        $_POST[$key] = stripslashes($value); 
    } 
}
What's $_POST["marketsource"]? An array. What happens when you pass that array to stripslashes() ? ;)
JeffBell
Forum Newbie
Posts: 15
Joined: Thu Feb 01, 2007 8:17 am

Post by JeffBell »

d11wtq wrote:What's $_POST["marketsource"]? An array. What happens when you pass that array to stripslashes() ? ;)
Frankly, I'm still not sure. I did get it beat into my brain that an array is not a string and that stripslashes is a function written for strings. I could not discover what actually happens when you give stripslashes an array, however. I just learned it "don't work."

After casting about for various possible ideas, I stumbled across this solution that seems to work.

Code: Select all

/** 2 **/
//See if evil magic_quotes is enabled, and fix problems if it is
$quotes_on = (get_magic_quotes_gpc() || get_magic_quotes_runtime());
if ($quotes_on)
{
    foreach ($_POST as $key => $value)
    {
//        $_POST[$key] = stripslashes($value);
//        if (is_array($_POST)) $_POST[$key] = stripslashes(&$value);
//        else $_POST[$key] = stripslashes($value);
//        if (is_array($_POST)) array_map($_POST[$key] = stripslashes(&$value));
//        else $_POST[$key] = stripslashes($value);
//        if (is_array($value)) array_walk($_POST[$key] = stripslashes(&$value));
//        else $value = stripslashes($value);
        if (is_array($value)) 
		  		{
            foreach ($value as $index => $value)
               {
                $value[$index] = stripslashes($value);
               }
				}
        else $_POST[$key] = stripslashes($value);
    }
}
Now, I can get my values from the checkboxes to be in the email contents.

Last problem: I still get a headers conflict which I don't see how to eliminate.

Code: Select all

Warning: Cannot modify header information - headers already sent by (output started at /usr/local/apache/hosts/domain/pub/parseandsend.php:6) in /usr/local/apache/hosts/domain/pub/parseandsend.php on line 178
What is triggering that? It only happens when one of my post values is an array. If I had all text input types, then this doesn't happen.

Relevant code

Code: Select all

{
    unset($_SESSION["post"]); //It worked, we have no reason to keep this data
    $swift->close();
    header("Location: contact_us_thanks.php"); /** 13 **/  //THIS IS LINE 178
    exit();
}
else
{
    $swift->close();
    header("Location: contact_us.php?error=runtime_error"); /** 13 **/
    exit();
}

UPDATE: I found I was still doing the var dump and commented that out, which solved the last error. 8) Thank you!
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Glad you got it sorted. To answer the question about why you get "Array" when passing an array to stripslashes(). stripslashes() expects a string, so by context, whatever you pass it will be turned into a string. If you turn an array into a string (this is called "casting" or "type-casting") PHP just makes the string "Array". stripslashes() was casting your array as a string (Array) then trying to take out \ from it before returning it, thus returning "Array". Because you then write that value back into $_POST["marketsource"], you replace the original array with a string.

Your solution will work well for your current version, but then what happens if you have an array inside another array. It only works up to two levels deep. I wouldn't stress over the solution but you may want to have a think about a (scalable) workaround for deeper nesting levels if you get bored ;)
BC Editor
Forum Newbie
Posts: 1
Joined: Sun Jul 06, 2014 1:48 pm

Re: Swift Mailer tutorial

Post by BC Editor »

hi Chris

you mention in your working script the following
/** 4 **/
//Load in the required Swift files
require_once "classes/Swift.php";
require_once "classes/Swift/Connection/SMTP.php";
I wanted to try this out but have problem in that there seems no file "lib/classes/Swift/Connection/SMTP.php" in my recent installation of Swift-5.1.0 ... would you have any information of changes since the time you wrote the above script and which file in the new Swift version needs to be entered here ?

Thanks
Post Reply