Ok, sorry for the delay, had a few visa things to sort out last night
So in the Swift code base there's an abstract class called Swift_Log (lib/Swift/Log.php).
This class is what defines the API for a log. You must extend it if you wish to provide your own Log implementation. Now, because it's abstract it forces you to implement 3 methods:
Code: Select all
/**
* Add a new entry to the log
* @param string The information to log
* @param string The type of entry (see the constants: COMMAND, RESPONSE, ERROR, NORMAL)
*/
abstract public function add($text, $type = self::NORMAL);
/**
* Dump the contents of the log to the browser.
* @param boolean True if the string should be returned rather than output.
*/
abstract public function dump($return_only=false);
/**
* Empty the log contents
*/
abstract public function clear();
So effectively to Log to a file you just want to implement add() so that it opens a file and writes to it:
Code: Select all
class FileLogger extends Swift_Log {
private $_logFile;
public function __construct($logFile) {
$this->_logFile = $logFile;
}
public function add($text, $type = self::NORMAL) {
$fp = fopen($this->_logFile, 'a'); //Append mode
flock($fp, LOCK_EX); //Make sure no other request is trying to write to the file!!
fwrite($fp, $type . $text . PHP_EOL); //Append the entry
fclose($fp);
}
// ... SNIP ...
}
So that's adding, but now we need to be able to clear() the log. Fortunately that's an easy fwrite(fp, '');
Code: Select all
public function clear() {
$fp = fopen($this->_logFile, 'w'); //Write mode
flock($fp, LOCK_EX); //Make sure no other request is trying to write to the file!!
fwrite($fp, '');
fclose($fp);
}
And finally we want to be able to dump() the log contents. This a bit tricker if we only want to dump() content from the current request rather than the entire log file which could potentially get pretty large. Using ftell() we can work out the offset.
Code: Select all
public function add( ... ) {
$fp = fopen($this->_logFile, 'a'); //Append mode
flock($fp, LOCK_EX); //Make sure no other request is trying to write to the file!!
if (!isset($this->_startOffset)) {
$this->_startOffset = ftell($fp);
}
// ... SNIP ...
}
public function dump($return_only=false) {
$fp = fopen($this->_logFile, 'r');
fseek($this->_logFile, $this->_startOffset, SEEK_SET);
$dump = '';
while (!feof($fp)) {
$dump .= fread($fp, 8192);
}
fclose($fp);
if ($return_only) {
return $dump;
} else {
echo $dump;
}
}
Putting that all together it looks like this:
Code: Select all
class FileLogger extends Swift_Log {
private $_logFile;
private $_startOffset;
public function __construct($logFile) {
$this->_logFile = $logFile;
}
public function add($text, $type = self::NORMAL) {
$fp = fopen($this->_logFile, 'a'); //Append mode
flock($fp, LOCK_EX); //Make sure no other request is trying to write to the file!!
if (!isset($this->_startOffset)) {
$this->_startOffset = ftell($fp);
}
fwrite($fp, $type . $text . PHP_EOL); //Append the entry
fclose($fp);
}
public function clear() {
$fp = fopen($this->_logFile, 'w'); //Write mode
flock($fp, LOCK_EX); //Make sure no other request is trying to write to the file!!
fwrite($fp, '');
fclose($fp);
}
public function dump($return_only=false) {
$fp = fopen($this->_logFile, 'r');
fseek($this->_logFile, $this->_startOffset, SEEK_SET);
$dump = '';
while (!feof($fp)) {
$dump .= fread($fp, 8192);
}
fclose($fp);
if ($return_only) {
return $dump;
} else {
echo $dump;
}
}
}
Great! We have a custom built Log implementation. Now we need to make sure Swift is using it
Code: Select all
Swift_LogContainer::setLog(new FileLogger('/tmp/swift.log'));
$log = Swift_LogContainer::getLog();
$log->setLogLevel(4);
That should now be logging to a file at /tmp/swift.log
Tracking failures should be in the log file (lines starting with "!!"). There are however other ways of getting the failed address back out:
http://www.swiftmailer.org/wikidocs/v3/sending/batch (See "Checking Addresses which didn't deliver").