DKIM and DomainKeys with a relaying server

February 28th, 2010

If you have this kind of warning in the your mail relay logs :

“external host … attempted to send as …”

You have to configure the “internal hosts” allowed to use this relay :

dkim-filter :

vi /etc/dkim-filter.conf

###…

InternalHosts           /var/dkim-filter/internal.hosts

###

vim /var/dkim-filter/internal.hosts

###

127.0.0.1
relayed.mydomain
relayed2.mydomain

###

/etc/init.d/dkim-filter restart

dk-filter:

use the -i option :

vim /etc/default/dk-filter

-i /var/dk-filter/interal.hosts

vim /var/dk-filter/interal.hosts

###

127.0.0.1
relayed.mydomain
relayed2.mydomain

###

/etc/init.d/dk-filter restart

InternalHosts           /var/dkim-filter/internal.hostsInternalHosts           /var/dkim-filter/internal.hos###

admin Mail server admin

Howto DKIM and DomainKeys on Debian Lenny with Postfix

February 16th, 2010

DomainKeys is still widely used but the standard is DKIM.
We will install both on a Debian Lenny system using postfix.

######### DKIM MILTER

aptitude install dkim-filter

mkdir /var/dkim-filter

dkim-genkey -b 1024 -d mydomain -s dkim.mydomain

chown -R dkim-filter . ; chmod 400

cat mydomain.txt

add the public key in the DNS config:

vim /etc/bind/pri/mydomain.hosts

###…

dkim.mydomain._domainkey IN TXT “v=DKIM1; g=*; k=rsa; p=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”

###

vim /etc/dkim-filter.conf

###

Socket                  inet:8891@localhost

# Log to syslog

Syslog                  yes

# Required to use local socket with MTAs that access the socket as a non-

# privileged user (e.g. Postfix)

UMask                   002

# Sign for example.com with key in /etc/mail/dkim.key using

# selector ‘2007′ (e.g. 2007._domainkey.example.com)

Domain                  mydomain

KeyFile                 /var/dkim-filter/mydomain.private

Selector                dkim.mydomain

# Common settings. See dkim-filter.conf(5) for more information.

AutoRestart             no

Background              yes

Canonicalization        simple

DNSTimeout              5

Mode                    sv

SignatureAlgorithm      rsa-sha256

SubDomains              no

#UseSSPDeny             no

#ASPDiscard             no

#Version                        rfc4871

X-Header                no

###…

/etc/init.d/dkim-filter restart

######### DK MILTER

aptitude install dk-filter csh

mkdir /var/dk-filter

cd /var/dk-filter

/usr/share/doc/dk-filter/examples/gentxt.csh mydomain dk.mydomain

chown -R dk-filter . ; chmod 400

add the public key in the DNS config:

vim /etc/bind/pri/mydomain.hosts

###…

dk.mydomain._domainkey IN TXT “k=rsa; t=y; p=xxxxxxxxxxxxxxxxxxxxxx==”

###

vim /etc/default/dk-filter

###…

DAEMON_OPTS=”$DAEMON_OPTS -d mydomain -s /var/dk-filter/mydomain.private -S dk.mydomain”

SOCKET=”net:8892@localhost”

###

######### POSTFIX

vi /etc/postfix/main.cf

###…

milter_default_action = accept

milter_protocol = 2

smtpd_milters = inet:localhost:8891 inet:localhost:8892

non_smtpd_milters = inet:localhost:8891 inet:localhost:8892

###

/etc/init.d/postfix restart

/etc/init.d/dk-filter restart

rndc-reload

#(Do not forget to increment your DNS zone serial # before)

If you have an ATT Yahoo account it’s perfect for testing.

Send an email from your server it should pass both test once received by ATT Yahoo.


admin Mail server admin , , , , , , , ,

CakePHP binding model associations dynamically

January 27th, 2010

Binding model associations dynamically with CakePHP :

In the Model file :

var $bindings = array(
‘belongsTo’ => array(
‘User’ => array(
‘className’ => ‘User’,
‘foreignKey’ => ‘user_id’,
‘dependent’ => false,
‘fields’ => ”,
‘order’ => ”
)
),
‘hasMany’ => array(
‘Message’ => array(
‘className’ => ‘Message’,
‘foreignKey’ => ‘classified_id’,
‘dependent’ => false
)
)
);

var $bindings = array(

‘belongsTo’ => array(

‘User’ => array(

‘className’ => ‘User’,

‘foreignKey’ => ‘user_id’,

‘dependent’ => false,

‘fields’ => ”,

‘order’ => ”

)

),

‘hasMany’ => array(

‘Message’ => array(

‘className’ => ‘Message’,

‘foreignKey’ => ‘classified_id’,

‘dependent’ => false

)

)

);

In the app_model.php :

function expects($array) {

$this->bindModel(array($array['type'] => array($array['model']=>$this->bindings[$array['type']][$array['model']])));

}

And then call it when needed in a controller :

$this->Classified->expects(array(’type’=>’belongsTo’,'model’=>’User’));

$this->Classified->expects(array(’type’=>’hasMany’,'model’=>’Message’));

It works !

admin CakePHP, Web development , , , ,

Installing Mailman on Gentoo Qmail Vpopmail

November 13th, 2009

Configure options : change the group and user used by apache to nobody.

EXTRA_ECONF=”–with-cgi-gid=nobody –with-cgi-uid=nobody –with-mail-gid=vchkpw” emerge -a mailman

Create a subdomain and edit the vhost in /etc/httpd/httpd.conf :

<VirtualHost xxx.xxx.xxx.xxx:80>
ServerAdmin webmaster@domain.com
DocumentRoot /home/domain/sd/mailman/www
ServerName mailman.domain.com
CustomLog logs/mailman.domain.com-access_log combined
ScriptAlias /mailman /usr/lib/mailman/cgi-bin/
AddHandler x-httpd-php5 .php
</VirtualHost>

Add the MAILMAN option to $APACHE2_OPTS in /etc/conf.d/apache

Copy mailman icon images to your vhost www :
cp -R /usr/lib/mailman/icons/ /home/domain/sd/mmm/www/
mv /home/domain/sd/mmm/www/icons /home/domain/sd/mmm/www/mailman-icons

Add the vhost domain to mailman config file mm_cfg.py :
add_virtualhost(DEFAULT_URL_HOST, DEFAULT_EMAIL_HOST)

In /etc/group make sure the user mailman is part of the cron group :
cron:x:16:mailman

Add the cron jobs :

su – mailman
cd /usr/lib/mailman/cron
crontab crontab.in
cd ..

Create password and main list :

bin/mmsitepass
bin/newlist mailman

Check and repair mailman permissions :
/usr/lib/mailman/bin/check_perms -f

Start the mailman daemon :
/etc/init.d/mailman start

Add to default runlevel :
rc-update add mailman default

Add the subdomain to bind :

subdomain1 IN A IPv4
subdomain1 IN MX 10 mail.domain.com.

restart bind /etc/init.d/named restart

Go to /home/vpopmail/domains/

Use the vpopmail tools to create your mailman subdomain :
/home/vpopmail/bin/vadddomain mailman.domain.com

This will add the subdomain to qmail files like /var/qmail/control/rcpthosts

We can create aliases manually or use the qmail-to-mailman.py.
To make it work with each virtualhost, we need to tune it for each virtualhost.
We can have a qmail-to-mailman script for each virtualhost.

mkdir /home/virtualhost/sd/subdomain/bin
cp /usr/lib/mailman/bin/qmail-to-mailman.py /home/virtualhost/sd/subdomain/bin
chown -R mailman:mailman /home/virtualhost/sd/subdomain/bin
edit qmail-to-mailman.py and check if the paths and list admin email are ok.

edit this line :

local = re.sub(”^mailman-”,”",local)

and replace mailman by your subdomain.vhostdomain. (if mailman is the subdomain and vhostdomain.com is your domain) :

local = re.sub(”^mailman.vhostdomain.com-”,”",local)

Edit .qmail-default and put this in to hook up qmail with mailman via qmail-to-mailman.py :

|/var/qmail/bin/preline /home/domain/sd/subdomain/bin/qmail-to-mailman.py

Go to : http://mailman.mydomain.com/mailman/admin

It should work !

admin System admin , , , , , ,

US and non-US phone numbers regexp validation

July 25th, 2009

Here is a very useful regular expression. It allows validation of US and non-US phone numbers.
It allows ‘+’ prefix and ’spaces’ and ‘-’ characters.
It should work with all the current phone numbers in the world. If you find one that doesn’t match, please comment about it.

Regular expression :

/^((\+\d{1,3}(-| )?\(?\d\)?(-| )?\d{1,5})|(\(?\d{2,6}\)?))(-| )?(\d{3,4})(-| )?(\d{4})(( x| ext)\d{1,5}){0,1}$/

CakePHP validation rule :

‘phone’ => array(

‘notempty’ => array( 

‘rule’ => array(’custom’, ‘/^((\+\d{1,3}(-| )?\(?\d\)?(-| )?\d{1,5})|(\(?\d{2,6}\)?))(-| )?(\d{3,4})(-| )?(\d{4})(( x| ext)\d{1,5}){0,1}$/’), 

‘required’ => false, 

‘allowEmpty’ => true, 

‘message’ => ‘Invalide phone number’ 

)

)

admin CakePHP, Web development , , , ,

Boot OS X in verbose mode

June 20th, 2009

At startup, keep pressed “ALT+V” to boot in verbose mode.

To always boot in verbose mode, type this in terminal :

sudo nvram boot-args="-v"

To burn verbose booting off :

sudo nvram boot-args=

admin Apple, Macintosh , , , , ,

Safari address bar keyboard shortcut

June 20th, 2009

To quickly select Safari address bar : CMD+L

admin Apple, Macintosh , ,

Opening CakePHP .ctp files with Dreamweaver

June 17th, 2009

Edit Extensions.txt Dreamweaver configuration files.

It should be here on Microsoft Windows : ˜\Application Data\Adobe\Dreamweaver 9\Configuration
And another one should be here : C:\Program Files\Adobe\Adobe Dreamweaver CS3\configuration

On Apple Mac OS X the path should be : ˜/Library/Application\ Support/Adobe/Dreamweaver\ 9/Configuration/

 

Modify these 2 lines :

HTM,HTML,SHTM,SHTML, … PHTML,CTP:All Documents                    

 

PHP,PHP3,PHP4,PHP5,TPL,PHTML,CTP:PHP Files

Then edit /Applications/Adobe\ Dreamweaver\ CS3/configuration/DocumentTypes :

<documenttype id=”PHP_MySQL” servermodel=”PHP MySQL” internaltype=”Dynamic” winfileextension=”php,php3,php4,php5,phtml,ctp” macfileextension=”php,php3,php4,php5,phtml,ctp” file=”Default.php” writebyteordermark=”false”>

admin CakePHP, Web development , , , , , ,

Custom 404 error page with CakePHP

June 15th, 2009

1. Create your error layout in app/view/layouts/

2. Create your 404 error view in app/view/errors/

In /cake/libs/view/errors you will find all the default error views.

You can copy and paste error404.ctp in your app/view/errors directory or create a new file and customize this view as you like.

3. Set the error layout in app_controller.php

Then add this to your app_controller.php :

function _setErrorLayout() {  

  if ($this->name == ‘CakeError’) {  

    $this->layout = ‘error’;  

  }    

}              

function beforeRender () {  

  $this->_setErrorLayout();

}

admin CakePHP , , , , ,

CakePHP tips

June 2nd, 2009

I’ve just found a good list of tips there :

http://cake-php.blogspot.com/2006/09/21-things-you-must-know-about-cakephp.html

Easily creating static pages

I needed to create several pages that didn’t use any models and contained static data inside the default layout. My first thought was to create a controller for these pages and define an action for each static page I needed. However, this solution seemed tedious and would make it difficult to quickly add new pages. Enter the pages controller – simply create a view inside the views/pages/ folder and it’ll automatically be rendered in /pages. For example, if I created /views/pages/matt.thtml it would be accessible via http://www.example.com/pages/matt

Static pages – Adjusting the page title

If you’re using the pages controller and you need to change the page title, add the following to your view: 
<? $this->pageTitle = 'Title of your page.'; ?>

Static pages – Adjusting other data sent to the layout

If you need to send data to the layout (such as a variable indicating what section to highlight on the nav bar), add this to your view:

<? $this->_viewVars['somedata'] = array('some','data'); ?>

That array should then be accessible as $somedata inside your layout.

Creating a simple admin center

If you need to create an administrative back-end for your CakePHP site and would like all the actions with administrative capabilities to exist under a specific folder, open up config/core.php and uncomment: 
define(’CAKE_ADMIN’, ‘admin’);
This will then make all actions that are prefixed with “admin_” to be accessible via: 
/admin/yourcontroller/youraction. For instance, if I created an action in my posts controller called “admin_add,” I would access this via: www.example.com/admin/posts/add
From there I could simply password the admin folder to prohibit unwanted users from adding posts.

Viewing the SQL queries that are running behind the scenes

You can easily see the SQL queries that CakePHP is running by adjusting the DEBUG constant in config/core.php. 0 is production, 1 is development, 2 is full debug with SQL, and 3 is full debug with SQL and dump of the current object. I typically have debug set at 2, which renders a table at the bottom of the page that contains SQL debug information. 
If rendering a table at the bottom of your site is constantly breaking your layout during development (especially if you’re making AJAX calls and you’re getting SQL inside your pages, not just the bottom), you can easily style this table to be hidden by adding this to your CSS: 
.cakeSqlLog { display: none; } 
This will allow you to view debug information in the HTML source code without your layout getting mangled, just don’t forget to set debug back to 0 when your site goes live.

Multiple sources of documentation

Don’t just rely on the manual. The wiki and the API are invaluable sources of information. The tutorials in the wiki are especially useful, and the API may be daunting at first, but you’ll quickly find the information in there is crucial to building a site with CakePHP.

Using bake.php

Bake is a command line PHP script that will automagically generate a model, controller, and views based on the design of your database. I highly recommend using scaffolding to get a prototype going of a table that may change a lot in the beginning. If you’re fairly certain the data is not subject to any drastic change, I recommend using bake instead. With bake all the files are generated and written to disk and you can make modifications from there. It saves a lot of time doing the repetitive tasks such as creating associations, views, and the basic CRUD controller operations. 
Using bake is really easy. Once you have a table(s) in your database created, change directories to the /cake/scripts/ folder and run: 
php bake.php
If you choose to bake interactively it’ll walk you through the steps required to create your model, controller, and views. Once everything has been baked I usually go through all the generated code and make custom modifications as needed.

Mind permissions when moving cake around

When I changed from the development server to the live server I tarred up my entire cake directory and scp’d it to the new server. Immediately I started having an issue where any time the debug level was set to 0 (production mode), data would not be returned for certain database calls. This was a bit of a catch 22 since I needed to view debug information to troubleshoot the problem. 
Someone in #cakephp kindly pointed out that permissions on the /app/tmp folder need to be writeable by apache. I changed the permissions to 777 and the issue went away.

Complex model validation

I needed to validate beyond just checking to make sure a field wasn’t empty or it matched a regular expression. In particular, I needed a way to verify that the email address users registered with was unique. In the wiki I found this gem: this advanced validation tutorial, which covers some advanced methods of validation that were very useful.

Logging errors

$this->log('Something broke'); 
This will log your error to /tmp/logs/ (I initially made the mistake of thinking it would log it to the apache error log)

Creating a controller that uses other models

Suppose you have a controller that needs data from a bunch of different models, simply add this to the top of your controller: 
class yourController extends AppController 
{
var $uses = array('Post','User'); 
} 

This controller would then have access to both the Post and the User model.

Creating a model for a table that doesn’t actually exist in the database

I needed a way to create a model and controller without actually having an associated table in the database. I particularly wanted to make use of the $validate array so I could easily validate my fields and keep the validation logic in the model. CakePHP will throw an error if you create a model for a table that doesn’t exist. Adding this to the model fixed the problem: 
var $useTable = false;
You can use this to change tables names as well. 
var $useTable = 'some_table';

Call exit() after redirecting

This should be no surprise to anyone who has done any serious web development in the past, but make sure you call exit() after running$this->redirect() if there’s code afterward that you don’t want to run. I’ve always done this in the past, but I made the assumption that$this->redirect() would make an exit call for me (which it didn’t).

Advanced model functions

Unless you delve in to the API, there are some very useful model functions at your disposal you might not know exist. I highly recommend reading over the Model Class Reference at least once. Here’s a few key functions I wasn’t aware of that I found to be very useful:

  • generateList() - I use this function primarily to populate select boxes with data from associated tables
  • findBySql() - Sometimes you just need to write your own SQL
  • findCount() - Returns number of rows matching given SQL condition
  • hasAny() - Returns true if a record that meets the given conditions exists.

Again, I highly recommend reading over the entire model class reference, you’ll be surprised at what you learn.

Inserting multiple rows in succession

I had a situation where I needed to iterate through a list of items and insert new rows for each. I quickly discovered that if you insert an item and then immediately insert another, the item that is inserted next doesn’t insert at all. Instead the previously inserted row was being updated. For example: 
$items = array('Item 1','Item 2','Item 3'); 
foreach ($items as $item) { 
  $this->Post->save(array('Post' => array('title' => $item))); 
}

This code will result in a single entry in the posts table: “item 3.” CakePHP inserted “item 1″, but then updates it to become “item 2,” then “item 3″ because $this->Post->id gets the value of the last inserted ID. Normally this functionality is very useful, but in this particular instance it was not. I found was to setting $this->Post->id = false after each insert solved the problem.

Inserting logic before or after controller functions

Suppose you needed an array of colors to be available to every view rendered by your controller but you don’t want to have to define this data in every action. Using the beforeRender() callback will allow you to do this: 
function beforeRender() {
  $this->set('colors',array('red','blue','green'); 
}

This would make $colors accessible in every view rendered by that controller. beforeRender() is called after the controller logic and just before a view is rendered. 
There’s also beforeFilter() and afterFilter(), which are called before and after every controller action. For more information, read up on callbacks in the models section of the manual.

Adding a WYSIWYG editor to CakePHP

I found this great tutorial on getting TinyMCE set up with CakePHP. Basically you just link the tiny_mce .js file to your page and then add a small bit of init code to every page that you want textareas to be converted into TinyMCE editors.

Writing your own SQL for HABTM relationships

I had an issue with trying to create a HABTM (has-and-belongs-to-many) relationship where I needed to specify my own SQL statement. According to the docs (at the time of this writing) you should set finderSql in your model, but according to the cakePHP source you should set finderQuery instead. It’s just a foul-up in the docs, but I figured it’d be worth noting to save others from having to figure it out for themselves. Trac ticket here: https://trac.cakephp.org/ticket/1217

Sending email

I found two tutorials in the wiki: Sending email and Sending email with PHPMailer
I highly recommend the latter of the two, sending emails with PHPMailer is more secure and there’s less of a headache because you don’t have to deal with constructing the mail headers yourself.

Customizing HTML generated by the Helper

I needed to change the default <option> generated when I called$html->selectTag() to say something like “Please Select” rather than an empty space (default). I also wanted radio buttons to have labels so the user doesn’t have to click exactly on the radio button itself but can instead click anywhere on the text associated with it. 
Create the file /app/config/tags.ini.php and add the following:
; Tag template for a input type='radio' tag.
radio = "<input type="radio" name="data[%s][%s]" id="%s" %s /><label for="%3$s">%s</label>"
; Tag template for an empty select option tag.
selectempty = "<option value="" %s>-- Please Select --</option>"

You can get a full list of available tags in /cake/config/tags.ini.php. I wouldn’t recommend modifying that file, however, because you could lose your changes when you upgrade CakePHP.

Creating a custom 404 error page

If you need to change the page that users see when a document is not found, create:
/app/views/errors/error404.thtml

admin CakePHP, Web development