Issue coupon on newsletter signup

This is not available out the box, and no rule would make this happen. You would need to do some custom code to make this work, as well as utilize mailchimps callback hooks to allow you to issue coupons on a successful subscription confirmation.

So lets start:

The first step is to go create a Shopping Cart Price Rule, and in the configuration, you set it to use a 'Specific Coupon', and then tick 'Use auto Generation' - do not generate coupons. This will be done via code from the mailchimp callback hook.

Create a controller action in your module. This is the callback hook that you will configure in mailchimp.

The controller would do a bit of basic validation to make sure it comes from the callback, and then use a model to handle the coupon generation and emailing thereof.

In mailchmimp you would set the hook as follows: (the wkey is just a random generated number, to ensure only the mailchimp hook can call the action)

mailchmip callback

Your controller action will look something like this: (note some irrelevant code removed)

class YourCompany_Mailingdriver_WebhookController extends Mage_Core_Controller_Front_Action
{

    /**
     * Entry point for all webhook operations
     */
    public function indexAction()
    {

        $requestKey = $this->getRequest()->getParam('wkey');

        //Checking if "wkey" para is present on request, we cannot check for !isPost()
        //because Mailchimp pings the URL (GET request) to validate webhook
        if( !$requestKey && $requestKey != '4ccd6d389b491419default'){
            $this->getResponse()
                ->setHeader('HTTP/1.1', '403 Forbidden')
                ->sendResponse();
            return $this;
        }

        Mage::app()->setCurrentStore(Mage::app()->getDefaultStoreView());

        Mage::log($this->getRequest()->getPost(), null, 'NewsletterPromotions_Mailingdriver_MonkeyApiCalls.log');

    $data  = $this->getRequest()->getPost();
    if(Mage::getIsDeveloperMode()) {
        $data = array('type'=>'subscribe',
              'data' => array('email'=>'[email protected]'),
              'list_id' => 'AAAAAAAAA');
    }
    if (array_key_exists('type',$data)) {
        Mage::getModel('mailingdriver/subscribe')->processWebhookData($data);
        } else {
            Mage::helper('monkey')->log($this->__('WebHook Data invalid!'));
        }  
    }

}

The actual work is done in the model method processWebhookData:

public function processWebhookData(array $data) {
        if (Mage::helper('mailingdriver')->canShow()) {
            if ($data['type'] == 'subscribe') {
                try {
                    $subscriber = Mage::getModel('newsletter/subscriber')
                            ->loadByEmail($data['data']['email']);
                     if ($this->canGetCoupon($subscriber)) { // only new subscribers can get a coupon.
            $this->sendCoupon($subscriber);
                        $subscriber->setNewSubscriber(0); // un-flag as new. Now only if they are physically deleted from magento subscriber list will they ever get another coupon
                    } else {
                        mage::log("subscriber {$subscriber->getEmail()} is not a new subscription", null, 'NewsletterPromotions_Mailingdriver_MonkeyApiCalls.log');
                        Mage::helper('mailingdriver/couponmailer')->sendNoCoupon($subscriber);
                    }
                } catch (Exception $e) {
                    Mage::logException($e);
                }
                $subscriber->setStatus(Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED)
                        ->save();
            }
        }
    }

The code above first checks to see if a person can get a coupon (this may not apply to your needs, but included for completness:

/**
     * Test if coupon can be issued
     *
     * @param object $subscriber
     * @return boolean
     */
    private function canGetCoupon($subscriber) {
    // new subscriber can get coupon, no issues.
    if ($subscriber->getNewSubscriber() == 1) {
        return true;
    }
    if ($subscriber->getStatus() != Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED) {
        // not a new subscriber, not subscribed (active), but is the date they unsubscribed older than the configured days in admin?
        $todayDate = strtotime(Mage::app()->getLocale()->date()->toString(Varien_Date::DATE_INTERNAL_FORMAT));
        $daysAllowed = Mage::helper('mailingdriver')->unsubscribePeriod();
        $statusChanged = strtotime($subscriber->getChangeStatusAt());
        $dateDiff = $todayDate - $statusChanged;
        $days = $dateDiff / (60 * 60 * 24);
        if ($days > $daysAllowed) {
        mage::log("subscriber {$subscriber->getEmail()} unsubscribed for {$days} - allowing coupon", null, 'NewsletterPromotions_Mailingdriver_MonkeyApiCalls.log');
        return true;
        }
    }
    return false;
    }

You will see the code above gets a numeric value for how many days a person should have been unsubscribed for, before they can again get a coupon. Adjust to your needs how you will populate that. The call is Mage::helper('mailingdriver')->unsubscribePeriod();

So, if they are valid to get a coupon, we generate one for them. This is done from a call in the sendCoupon method.

public function sendCoupon($subscriber) {
        if (!Zend_Validate::is($subscriber->getEmail(), 'EmailAddress')) {
            Mage::throwException(Mage::helper('mailingdriver')->__('Please enter a valid email address.'));
        }
        try {
            if ($coupon = $this->_generateCoupon()) {
                //send email
                Mage::helper('mailingdriver/couponmailer')->sendCoupon($subscriber, $coupon->getCode());
            }
        } catch (Exception $e) {
            mage::throwException($e->getMessage());
        }
    }

and finally the code that interacts with your created Cart rule, and creates the coupon. You can see in the code how the generated coupon will be formatted.

/**
     * Generate a coupon 
     * @throws Exception
     */
    protected function _generateCoupon() {
        /** @var $rule Mage_SalesRule_Model_Rule */
        $rule = Mage::getModel('salesrule/rule')->load(Mage::helper('mailingdriver')->getRuleId());
        if (!$rule->getId() && !$rule->getEnabled() != 1) {
            mage::throwException('Mailingdriver activated, but Shopping Cart Rule ID could not be found, or rule is disabled');
        }
        $data = array(
            'rule_id' => $rule->getId(),
            'qty' => 1,
            'length' => 5,
            'format' => 'alphanum',
            'prefix' => 'PREFIX-',
            'suffix' => '',
            'dash' => 0,
            'uses_per_coupon' => $rule->getUsesPerCoupon(),
            'uses_per_customer' => $rule->getUsesPerCustomer(),
            'to_date' => $rule->getToDate(),
        );
        try {
            $generator = $rule->getCouponMassGenerator();
            if (!$generator->validateData($data)) {
                mage::throwException('Not valid data provided to Mailingdriver to use coupon mass generator!');
            } else {
                $generator->setData($data);
                $generator->generatePool();
                $collection = Mage::getModel('salesrule/coupon')
                        ->getCollection()
                        ->addFieldToSelect('*');
                $collection->getSelect()
                        ->order('coupon_id DESC')
                        ->limit(1);
                if ($collection->Count() == 0) {
                    mage::throwException('Could not retrieve a valid coupon code after generated');
                }
                return $collection->getFirstItem();
            }
        } catch (Exception $e) {
            mage::throwException($e->getMessage());
        }
    }

in the code above Mage::helper('mailingdriver')->getRuleId() is the id of your Cart Promo Rule you created.

Hope that helps, and ask if you need some clarification on any of the code.