def handleApply(self, action): data, errors = self.extractData() if 'email' in data: # Fetch MailChimp settings registry = getUtility(IRegistry) mailchimp_settings = registry.forInterface(IMailchimpSettings) if len(mailchimp_settings.api_key) == 0: return mailchimp = PostMonkey(mailchimp_settings.api_key) # Fetch MailChimp lists # XXX, Todo: For now we just fetch the first list. try: lists = mailchimp.lists()['data'] list_id = lists[0]['id'] except MailChimpException, error: raise WidgetActionExecutionError( Invalid( _(u"Could not fetch list from mailchimp.com: %s" % error))) # Subscribe to MailChimp list try: mailchimp.listSubscribe(id=list_id, email_address=data['email']) except MailChimpException, error: raise WidgetActionExecutionError( 'email', Invalid(_(u"Could not subscribe to newsletter: %s" % error)))
def handleApply(self, action): data, errors = self.extractData() if 'email' in data: # Fetch MailChimp settings registry = getUtility(IRegistry) mailchimp_settings = registry.forInterface(IMailchimpSettings) if len(mailchimp_settings.api_key) == 0: return mailchimp = PostMonkey(mailchimp_settings.api_key) # Fetch MailChimp lists # XXX, Todo: For now we just fetch the first list. try: lists = mailchimp.lists()['data'] list_id = lists[0]['id'] except MailChimpException, error: raise WidgetActionExecutionError( Invalid(_(u"Could not fetch list from mailchimp.com: %s" % error))) # Subscribe to MailChimp list try: mailchimp.listSubscribe( id=list_id, email_address=data['email']) except MailChimpException, error: raise WidgetActionExecutionError( 'email', Invalid(_( u"Could not subscribe to newsletter: %s" % error)))
def handle_error(self, error, data): # Current api v3 documentation only lists errors in the 400 and 500 # range. The 400 code can mean a lot of things... if error.code == 400: error_msg = _( u"mailchimp_error_msg_already_subscribed", default=u"Could not subscribe to newsletter. " u"Either the email '${email}' is already subscribed " u"or something else is wrong. Try again later.", mapping={u"email": data['email']}, ) translated_error_msg = self.context.translate(error_msg) raise WidgetActionExecutionError('email', Invalid(translated_error_msg)) elif error.code == 220: error_msg = _( u"mailchimp_error_msg_banned", default=u"Could not subscribe to newsletter. " u"The email '${email}' has been banned.", mapping={u"email": data['email']}, ) translated_error_msg = self.context.translate(error_msg) raise WidgetActionExecutionError('email', Invalid(translated_error_msg)) else: error_msg = _( u"mailchimp_error_msg", default=u"Could not subscribe to newsletter. " u"Please contact the site administrator: " u"'${error}'", mapping={u"error": error}, ) translated_error_msg = self.context.translate(error_msg) raise ActionExecutionError(Invalid(translated_error_msg))
class INewsletterSubscribe(Interface): email = schema.TextLine( title=_(u"Email address"), description=_(u"help_email", default=u"Please enter your email address."), required=True, constraint=validate_email)
class MailchimpSettingsEditForm(controlpanel.RegistryEditForm): schema = IMailchimpSettings label = _(u"MailChimp settings") description = _(u"""""") def updateFields(self): super(MailchimpSettingsEditForm, self).updateFields() def updateWidgets(self): super(MailchimpSettingsEditForm, self).updateWidgets()
def handleApply(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return # Retrieve list_id either from a hidden field in the form or fetch # the first list from mailchimp. list_id = data.get('list_id') or self.mailchimp.default_list_id() # list_id has to be updated for merge_fields=data to work if None if "list_id" in data and not data.get('list_id'): data['list_id'] = list_id # interest groups interests = {} interest_groups = data.pop('interest_groups', []) if self.available_interest_groups and interest_groups: # Create dictionary with as keys the interest groups, and as # values always True. interests = dict.fromkeys(interest_groups, True) # Use email_type if one is provided by the form, if not choose the # default email type from the control panel settings. email_type = data.get( 'email_type') or self.mailchimp_settings.email_type # Subscribe to MailChimp list try: self.mailchimp.subscribe( list_id=list_id, email_address=data['email'], email_type=email_type, interests=interests, merge_fields=data, ) except MailChimpException as error: return self.handle_error(error, data) if self.mailchimp_settings.double_optin: message = _( u"We have to confirm your email address. In order to " + u"finish the newsletter subscription, click on the link " + u"inside the email we just send you.") else: message = _( u"You have been subscribed to our newsletter succesfully.") IStatusMessage(self.context.REQUEST).addStatusMessage(message, type="info") portal = getToolByName(self.context, 'portal_url').getPortalObject() site = getNavigationRootObject(self.context, portal) self.request.response.redirect(site.absolute_url())
def handle_unsubscribe(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return list_id = data.get('list_id') or self.mailchimp.default_list_id() email = data['email'] update_data = {} if data.get('unsubscribe'): update_data['status'] = 'unsubscribed' else: interest_groups = {} for group in data.get('interest_groups', []): interest_groups[group] = False update_data['interests'] = interest_groups try: self.mailchimp.update_subscriber( list_id, email_address=email, **update_data ) except MailChimpException as error: if error.code != 404: # If a subscriber did not exist we don't want to announce # it. Treat only != 404 as an error. IStatusMessage(self.request).addStatusMessage( _( u'mailchimp_unsubscribe_error_msg', default=u'We could not unsubscribe you from ' u'the newsletter. ' u"Please contact the site administrator: " u"'${error}'", mapping={u"error": error}, ), type="info", ) IStatusMessage(self.request).addStatusMessage( _( u'mailchimp_unsubscribed_msg', default=( u'Thank you. You have been unsubscribed from ' u'the Newsletter.' ), ), type="info", ) portal = getSite() self.request.response.redirect(portal.absolute_url())
def handle_unsubscribe(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return list_id = data.get('list_id') or self.mailchimp.default_list_id() email = data['email'] update_data = {} if data.get('unsubscribe'): update_data['status'] = 'unsubscribed' else: interest_groups = {} if data.get('interest_groups'): for group in data.get('interest_groups', []): interest_groups[group] = False update_data['interests'] = interest_groups try: self.mailchimp.update_subscriber(list_id, email_address=email, **update_data) except MailChimpException as error: if error.code != 404: # If a subscriber did not exist we don't want to announce # it. Treat only != 404 as an error. IStatusMessage(self.request).addStatusMessage( _( u'mailchimp_unsubscribe_error_msg', default=u'We could not unsubscribe you from ' u'the newsletter. ' u"Please contact the site administrator: " u"'${error}'", mapping={u"error": error}, ), type="info", ) IStatusMessage(self.request).addStatusMessage( _( u'mailchimp_unsubscribed_msg', default=(u'Thank you. You have been unsubscribed from ' u'the Newsletter.'), ), type="info", ) portal = getToolByName(self.context, 'portal_url').getPortalObject() site = getNavigationRootObject(self.context, portal) self.request.response.redirect(site.absolute_url())
def handleApply(self, action): data, errors = self.extractData() if 'email' not in data: return mailchimp = getUtility(IMailchimpLocator) # Retrieve list_id either from a hidden field in the form or fetch # the first list from mailchimp. if 'list_id' in data and data['list_id'] is not None: list_id = data['list_id'] else: list_id = mailchimp.default_list_id() # Groupings interests = {} if 'interest_groups' in data and data['interest_groups'] is not None: interest_grouping = mailchimp.groups(list_id=list_id) if interest_grouping and data['interest_groups']: # Create dictionary with as keys the interest groups, and as # values always True. interests = dict.fromkeys(data['interest_groups'], True) # Use email_type if one is provided by the form, if not choose the # default email type from the control panel settings. if 'email_type' in data: email_type = data['email_type'] else: email_type = 'HTML' # Subscribe to MailChimp list try: mailchimp.subscribe( list_id=list_id, email_address=data['email'], email_type=email_type, interests=interests ) except MailChimpException as error: return self.handle_error(error, data) registry = getUtility(IRegistry) mailchimp_settings = registry.forInterface(IMailchimpSettings) if mailchimp_settings.double_optin: message = _( u"We have to confirm your email address. In order to " + u"finish the newsletter subscription, click on the link " + u"inside the email we just send you.") else: message = _( u"You have been subscribed to our newsletter succesfully.") IStatusMessage(self.context.REQUEST).addStatusMessage( message, type="info") portal = getSite() self.request.response.redirect(portal.absolute_url())
def handleApply(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return # Retrieve list_id either from a hidden field in the form or fetch # the first list from mailchimp. list_id = data.get('list_id') or self.mailchimp.default_list_id() # interest groups interests = {} interest_groups = data.pop('interest_groups', []) if self.available_interest_groups and interest_groups: # Create dictionary with as keys the interest groups, and as # values always True. interests = dict.fromkeys(interest_groups, True) # Use email_type if one is provided by the form, if not choose the # default email type from the control panel settings. email_type = data.get('email_type', 'HTML') # Subscribe to MailChimp list try: self.mailchimp.subscribe( list_id=list_id, email_address=data['email'], email_type=email_type, interests=interests, merge_fields=data, ) except MailChimpException as error: return self.handle_error(error, data) if self.mailchimp_settings.double_optin: message = _( u"We have to confirm your email address. In order to " + u"finish the newsletter subscription, click on the link " + u"inside the email we just send you." ) else: message = _( u"You have been subscribed to our newsletter succesfully." ) IStatusMessage(self.context.REQUEST).addStatusMessage( message, type="info" ) portal = getSite() self.request.response.redirect(portal.absolute_url())
class NewsletterSubscriberForm(form.Form): fields = field.Fields(INewsletterSubscribe) ignoreContext = True label = _(u"Subscribe to newsletter") def updateActions(self): super(NewsletterSubscriberForm, self).updateActions() self.actions['subscribe'].addClass('context') @button.buttonAndHandler(_(u"subscribe_to_newsletter_button", default=u"Subscribe"), name='subscribe') def handleApply(self, action): data, errors = self.extractData() if 'email' in data: # Fetch MailChimp settings registry = getUtility(IRegistry) mailchimp_settings = registry.forInterface(IMailchimpSettings) if len(mailchimp_settings.api_key) == 0: return mailchimp = PostMonkey(mailchimp_settings.api_key) # Fetch MailChimp lists # XXX, Todo: For now we just fetch the first list. try: lists = mailchimp.lists()['data'] list_id = lists[0]['id'] except MailChimpException, error: raise WidgetActionExecutionError( Invalid( _(u"Could not fetch list from mailchimp.com: %s" % error))) # Subscribe to MailChimp list try: mailchimp.listSubscribe(id=list_id, email_address=data['email']) except MailChimpException, error: raise WidgetActionExecutionError( 'email', Invalid(_(u"Could not subscribe to newsletter: %s" % error))) IStatusMessage(self.context.REQUEST).addStatusMessage( _(u"We have to confirm your email address. In order to " + "finish the newsletter subscription, click on the link " + "inside the email we just send you."), type="info") portal = getSite() self.request.response.redirect(portal.absolute_url())
class INewsletterUnsubscribe(Interface): email = schema.TextLine( title=_(u"Email address"), description=_(u"help_email", default=u"Please enter your email address."), required=True, constraint=validate_email, ) list_id = schema.TextLine(title=_(u"List ID"), required=False) interest_groups = schema.Tuple( title=_( u'mailchimp_unsubscribe_interest_groups', default=u"Unsubscribe only form the following interest groups", ), description=_(u"mailchimp_help_unsubscribe_interest_groups", default=u""), value_type=schema.Choice( vocabulary="collective.mailchimp.vocabularies.InterestGroups"), required=False, ) unsubscribe = schema.Bool( title=_( u'mailchimp_unsubscribe_newsletter', default=u"Unsubscribe from the complete newsletter", ), description=_(u'mailchimp_help_unsubscribe_newsletter', default=u''), )
class MailchimpSettingsEditForm(controlpanel.RegistryEditForm): schema = IMailchimpSettings label = _(u"MailChimp settings") description = _(u"""""") def update(self): self.updateCache() super(MailchimpSettingsEditForm, self).update() def updateFields(self): super(MailchimpSettingsEditForm, self).updateFields() def updateWidgets(self): super(MailchimpSettingsEditForm, self).updateWidgets() def updateCache(self): mailchimp = getUtility(IMailchimpLocator) mailchimp.updateCache()
class INewsletterSubscribe(Interface): email = schema.TextLine(title=_(u"Email address"), description=_( u"help_email", default=u"Please enter your email address."), required=True, constraint=validate_email) interest_groups = schema.Tuple( title=_(u"Interest groups"), description=_(u"help_interest_groups", default=u""), value_type=schema.Choice( vocabulary="collective.mailchimp.vocabularies.InterestGroups", ), required=False, ) email_type = schema.Choice( title=_(u"Mail format"), vocabulary="collective.mailchimp.vocabularies.EmailType", default="text", required=False, ) list_id = schema.TextLine(title=_(u"List ID"), required=False)
def handle_error(self, error, data): # Current api v3 documentation only lists errors in the 400 and 500 # range. The 400 code can mean a lot of things... if error.code == 400: error_msg = _( u"mailchimp_error_msg_already_subscribed", default=u"Could not subscribe to newsletter. " u"Either the email '${email}' is already subscribed " u"or something else is wrong. Try again later.", mapping={u"email": data['email']}) translated_error_msg = self.context.translate(error_msg) raise WidgetActionExecutionError( 'email', Invalid(translated_error_msg) ) elif error.code == 220: error_msg = _( u"mailchimp_error_msg_banned", default=u"Could not subscribe to newsletter. " u"The email '${email}' has been banned.", mapping={u"email": data['email']}) translated_error_msg = self.context.translate(error_msg) raise WidgetActionExecutionError( 'email', Invalid(translated_error_msg) ) else: error_msg = _( u"mailchimp_error_msg", default=u"Could not subscribe to newsletter. " u"Please contact the site administrator: " u"'${error}'", mapping={u"error": error}) translated_error_msg = self.context.translate(error_msg) raise ActionExecutionError( Invalid(translated_error_msg) )
class NewsletterSubscriberForm(extensible.ExtensibleForm, form.Form): fields = field.Fields(INewsletterSubscribe) ignoreContext = True id = "newsletter-subscriber-form" label = _(u"Subscribe to newsletter") def updateActions(self): super(NewsletterSubscriberForm, self).updateActions() self.actions['subscribe'].addClass('context') def updateFields(self): super(NewsletterSubscriberForm, self).updateFields() self.fields['interest_groups'].widgetFactory = \ CheckBoxFieldWidget self.fields['email_type'].widgetFactory = \ RadioFieldWidget def updateWidgets(self): super(NewsletterSubscriberForm, self).updateWidgets() # Show/hide mail format option widget registry = getUtility(IRegistry) mailchimp_settings = registry.forInterface(IMailchimpSettings) if not mailchimp_settings.email_type_is_optional: self.widgets['email_type'].mode = HIDDEN_MODE # Retrieve the list id either from the request/form or fall back to # the default_list setting. if 'list_id' in self.context.REQUEST: list_id = self.context.REQUEST['list_id'] elif 'form.widgets.list_id' in self.request.form: list_id = self.request.form['form.widgets.list_id'] else: list_id = mailchimp_settings.default_list self.widgets['list_id'].mode = HIDDEN_MODE self.widgets['list_id'].value = list_id # Show/hide interest_groups widget mailchimp = getUtility(IMailchimpLocator) groups = mailchimp.groups(list_id=list_id) if not groups: self.widgets['interest_groups'].mode = HIDDEN_MODE if 'preselect_group' in self.context.REQUEST: for group_index in self.request['preselect_group']: group_index = int(group_index) self.widgets['interest_groups']\ .items[group_index]['checked'] = True @button.buttonAndHandler(_(u"subscribe_to_newsletter_button", default=u"Subscribe"), name='subscribe') def handleApply(self, action): data, errors = self.extractData() if 'email' in data: mailchimp = getUtility(IMailchimpLocator) # Retrieve list_id either from a hidden field in the form or fetch # the first list from mailchimp. if 'list_id' in data: list_id = data['list_id'] else: list_id = mailchimp.default_list_id() # Groupings if 'interest_groups' in data: interest_grouping = mailchimp.groups(list_id=list_id) if interest_grouping and data['interest_groups']: data['groupings'] = [{ 'id': interest_grouping['id'], 'groups': ",".join(data['interest_groups']), }] # Use email_type if one is provided by the form, if not choose the # default email type from the control panel settings. if 'email_type' in data: email_type = data['email_type'] else: email_type = None # Subscribe to MailChimp list try: mailchimp.subscribe( list_id=list_id, email_address=data['email'], merge_vars=data, email_type=email_type, ) except MailChimpException, error: if error.code == 214: error_msg = _( u"mailchimp_error_msg_already_subscribed", default=u"Could not subscribe to newsletter. " u"The email '${email}' is already subscribed.", mapping={u"email": data['email']}) translated_error_msg = self.context.translate(error_msg) raise WidgetActionExecutionError( 'email', Invalid(translated_error_msg)) elif error.code == 220: error_msg = _( u"mailchimp_error_msg_banned", default=u"Could not subscribe to newsletter. " u"The email '${email}' has been banned.", mapping={u"email": data['email']}) translated_error_msg = self.context.translate(error_msg) raise WidgetActionExecutionError( 'email', Invalid(translated_error_msg)) else: error_msg = _( u"mailchimp_error_msg", default=u"Could not subscribe to newsletter. " u"Please contact the site administrator: " u"'${error}'", mapping={u"error": error}) translated_error_msg = self.context.translate(error_msg) raise ActionExecutionError(Invalid(translated_error_msg)) IStatusMessage(self.context.REQUEST).addStatusMessage( _(u"We have to confirm your email address. In order to " + u"finish the newsletter subscription, click on the link " + u"inside the email we just send you."), type="info") portal = getSite() self.request.response.redirect(portal.absolute_url())
class NewsletterSubscriberForm(extensible.ExtensibleForm, form.Form): fields = field.Fields(INewsletterSubscribe) ignoreContext = True id = "newsletter-subscriber-form" label = _(u"Subscribe to newsletter") def updateActions(self): super(NewsletterSubscriberForm, self).updateActions() self.actions['subscribe'].addClass('context') def updateFields(self): super(NewsletterSubscriberForm, self).updateFields() self.fields['interest_groups'].widgetFactory = CheckBoxFieldWidget self.fields['email_type'].widgetFactory = RadioFieldWidget def updateWidgets(self): super(NewsletterSubscriberForm, self).updateWidgets() widgets = self.widgets registry = getUtility(IRegistry) self.mailchimp_settings = registry.forInterface(IMailchimpSettings) self.mailchimp = getUtility(IMailchimpLocator) # Show/hide mail format option widget if not self.mailchimp_settings.email_type_is_optional: widgets['email_type'].mode = HIDDEN_MODE # Retrieve the list id either from the request/form or fall back to # the default_list setting. list_id = self.context.REQUEST.get('list_id') list_id = list_id or self.request.form.get('form.widgets.list_id') list_id = list_id or self.mailchimp_settings.default_list widgets['list_id'].mode = HIDDEN_MODE widgets['list_id'].value = list_id # Show/hide interest_groups widget self.available_interest_groups = self.mailchimp.groups(list_id=list_id) if not self.available_interest_groups or \ self.available_interest_groups.get('total_items') == 0: widgets['interest_groups'].mode = HIDDEN_MODE preselected_groups = self.request.get('preselected_group', []) for group_index in preselected_groups: group_index = int(group_index) widgets['interest_groups'].items[group_index]['checked'] = True @button.buttonAndHandler( _(u"subscribe_to_newsletter_button", default=u"Subscribe"), name='subscribe', ) def handleApply(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return # Retrieve list_id either from a hidden field in the form or fetch # the first list from mailchimp. list_id = data.get('list_id') or self.mailchimp.default_list_id() # list_id has to be updated for merge_fields=data to work if None if "list_id" in data and not data.get('list_id'): data['list_id'] = list_id # interest groups interests = {} interest_groups = data.pop('interest_groups', []) if self.available_interest_groups and interest_groups: # Create dictionary with as keys the interest groups, and as # values always True. interests = dict.fromkeys(interest_groups, True) # Use email_type if one is provided by the form, if not choose the # default email type from the control panel settings. email_type = data.get( 'email_type') or self.mailchimp_settings.email_type # Subscribe to MailChimp list try: self.mailchimp.subscribe( list_id=list_id, email_address=data['email'], email_type=email_type, interests=interests, merge_fields=data, ) except MailChimpException as error: return self.handle_error(error, data) if self.mailchimp_settings.double_optin: message = _( u"We have to confirm your email address. In order to " + u"finish the newsletter subscription, click on the link " + u"inside the email we just send you.") else: message = _( u"You have been subscribed to our newsletter succesfully.") IStatusMessage(self.context.REQUEST).addStatusMessage(message, type="info") portal = getToolByName(self.context, 'portal_url').getPortalObject() site = getNavigationRootObject(self.context, portal) self.request.response.redirect(site.absolute_url()) def handle_error(self, error, data): # Current api v3 documentation only lists errors in the 400 and 500 # range. The 400 code can mean a lot of things... if error.code == 400: error_msg = _( u"mailchimp_error_msg_already_subscribed", default=u"Could not subscribe to newsletter. " u"Either the email '${email}' is already subscribed " u"or something else is wrong. Try again later.", mapping={u"email": data['email']}, ) translated_error_msg = self.context.translate(error_msg) raise WidgetActionExecutionError('email', Invalid(translated_error_msg)) elif error.code == 220: error_msg = _( u"mailchimp_error_msg_banned", default=u"Could not subscribe to newsletter. " u"The email '${email}' has been banned.", mapping={u"email": data['email']}, ) translated_error_msg = self.context.translate(error_msg) raise WidgetActionExecutionError('email', Invalid(translated_error_msg)) else: error_msg = _( u"mailchimp_error_msg", default=u"Could not subscribe to newsletter. " u"Please contact the site administrator: " u"'${error}'", mapping={u"error": error}, ) translated_error_msg = self.context.translate(error_msg) raise ActionExecutionError(Invalid(translated_error_msg))
class IMailchimpSettings(Interface): """Global mailchimp settings. This describes records stored in the configuration registry and obtainable via plone.registry. """ api_key = schema.TextLine( title=_(u"MailChimp API Key"), description=_(u"help_api_key", default=u"Enter in your MailChimp key here (.e.g. " + "'8b785dcabe4b5aa24ef84201ea7dcded-us4'). Log into " + "mailchimp.com, go to account -> extras -> API Keys & " + "Authorized Apps and copy the API Key to this field."), default=u"", required=True) debug = schema.Bool( title=_(u"Debug MailChimp"), description=_(u"help_debug", default=u""), required=True, default=False) ssl = schema.Bool( title=_(u"SSL"), description=_(u"help_ssl", default=u""), required=True, default=True) cache_sec = schema.Int( title=_(u"Cache Sec"), description=_(u"help_cache_sec", default=u""), required=True, default=500) available_fields = schema.Choice( title=_(u"Available fields"), description=_(u"help_available_fields", default=u""), vocabulary=available_fields, required=False) lists_email_type = schema.TextLine( title=_(u"lists_email_type"), description=_(u"help_lists_email_type", default=u""), required=True, default=u'html',) lists_double_optin = schema.Bool( title=_(u"lists_double_optin"), description=_(u"help_lists_double_optin", default=u""), required=True, default=True) lists_update_existing = schema.Bool( title=_(u"lists_update_existing"), description=_(u"help_lists_update_existing", default=u""), required=True, default=False) lists_replace_interests = schema.Bool( title=_(u"lists_replace_interests"), description=_(u"help_lists_replace_interests", default=u""), required=True, default=True) @invariant def valid_api_key(obj): registry = getUtility(IRegistry) mailchimp_settings = registry.forInterface(IMailchimpSettings) if len(mailchimp_settings.api_key) == 0: return mailchimp = PostMonkey(mailchimp_settings.api_key) try: return mailchimp.ping() except: raise Invalid(u"Your MailChimp API key is not valid. Please go " + "to mailchimp.com and check your API key.")
class IMailchimpSettings(Interface): """Global mailchimp settings. This describes records stored in the configuration registry and obtainable via plone.registry. """ api_key = schema.TextLine( title=_(u"MailChimp API Key"), description=_( u"help_api_key", default=u"Enter in your MailChimp key here (.e.g. " + u"'8b785dcabe4b5aa24ef84201ea7dcded-us4'). Log into " + u"mailchimp.com, go to account -> extras -> API Keys & " + u"Authorized Apps and copy the API Key to this field."), default=u"", required=True) email_type = schema.Choice( title=_(u"email_type"), description=_( u"help_email_type", default=u"Email type preference for the email (html, text, or " u"mobile defaults to html)"), vocabulary="collective.mailchimp.vocabularies.EmailType", default="text", required=True, ) email_type_is_optional = schema.Bool( title=_(u"email_type_is_optional"), description=_( u"help_email_type_is_optional", default=u"Let users choose their email type preference in the " u"newsletter subscription form."), required=True, default=False) default_list = schema.Choice( title=_(u"default_list"), description=_( u"help_default_list", default=u"Default list which is used in the @@newsletter view if " u"no list_id param is provided."), vocabulary="collective.mailchimp.vocabularies.AvailableLists", required=False, ) double_optin = schema.Bool( title=_(u"double_optin"), description=_( u"help_double_optin", default=u"Flag to control whether a double opt-in confirmation " u"message is sent, defaults to true. Abusing this may " u"cause your account to be suspended."), required=True, default=True) update_existing = schema.Bool( title=_(u"update_existing"), description=_( u"help_update_existing", default=u"Flag to control whether existing subscribers should be " u"updated instead of throwing an error, defaults to false"), required=True, default=False) replace_interests = schema.Bool( title=_(u"replace_interests"), description=_( u"help_replace_interests", default=u"Flag to determine whether we replace the interest " u"groups with the groups provided or we add the provided" u"groups to the member's interest groups (optional, " u"defaults to true)"), required=True, default=True) send_welcome = schema.Bool( title=_(u"send_welcome"), description=_( u"help_send_welcome", default=u"If your double_optin is false and this is true, we " u"will send your lists Welcome Email if this subscribe " u"succeeds - this will *not* fire if we end up updating " u"an existing subscriber. If double_optin is true, this " u"has no effect. defaults to false."), required=True, default=False) @invariant def valid_api_key(data): if len(data.api_key) == 0: return mailchimp = PostMonkey(data.api_key) try: return mailchimp.ping() except: raise Invalid(u"Your MailChimp API key is not valid. Please go " + u"to mailchimp.com and check your API key.")
class NotAnEmailAddress(schema.ValidationError): __doc__ = _(u"Invalid email address")
def handleApply(self, action): data, errors = self.extractData() if 'email' in data: mailchimp = getUtility(IMailchimpLocator) # Retrieve list_id either from a hidden field in the form or fetch # the first list from mailchimp. if 'list_id' in data: list_id = data['list_id'] else: list_id = mailchimp.default_list_id() # Groupings if 'interest_groups' in data: interest_grouping = mailchimp.groups(list_id=list_id) if interest_grouping and data['interest_groups']: data['groupings'] = [ { 'id': interest_grouping['id'], 'groups': ",".join(data['interest_groups']), } ] # Use email_type if one is provided by the form, if not choose the # default email type from the control panel settings. if 'email_type' in data: email_type = data['email_type'] else: email_type = None # Subscribe to MailChimp list try: mailchimp.subscribe( list_id=list_id, email_address=data['email'], merge_vars=data, email_type=email_type, ) except MailChimpException, error: if error.code == 214: error_msg = _( u"mailchimp_error_msg_already_subscribed", default=u"Could not subscribe to newsletter. " u"The email '${email}' is already subscribed.", mapping={ u"email": data['email'] } ) translated_error_msg = self.context.translate(error_msg) raise WidgetActionExecutionError( 'email', Invalid(translated_error_msg) ) elif error.code == 220: error_msg = _( u"mailchimp_error_msg_banned", default=u"Could not subscribe to newsletter. " u"The email '${email}' has been banned.", mapping={ u"email": data['email'] } ) translated_error_msg = self.context.translate(error_msg) raise WidgetActionExecutionError( 'email', Invalid(translated_error_msg) ) else: error_msg = _( u"mailchimp_error_msg", default=u"Could not subscribe to newsletter. " u"Please contact the site administrator: " u"'${error}'", mapping={ u"error": error } ) translated_error_msg = self.context.translate(error_msg) raise ActionExecutionError( Invalid(translated_error_msg) ) IStatusMessage(self.context.REQUEST).addStatusMessage(_( u"We have to confirm your email address. In order to " + u"finish the newsletter subscription, click on the link " + u"inside the email we just send you."), type="info" ) portal = getSite() self.request.response.redirect(portal.absolute_url())
import re from postmonkey import PostMonkey from zope import schema from zope.interface import Interface from zope.interface import invariant from zope.interface import Invalid from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm from collective.mailchimp import _ available_fields = SimpleVocabulary([ SimpleTerm(value=u'subscriber_list', title=_(u'Subscriber list')), SimpleTerm(value=u'email', title=_(u'E-Mail')) ]) class ICollectiveMailchimp(Interface): """Marker interface that defines a ZTK browser layer. We can reference this in the 'layer' attribute of ZCML <browser:* /> directives to ensure the relevant registration only takes effect when this theme is installed. The browser layer is installed via the browserlayer.xml GenericSetup import step. """ class NotAnEmailAddress(schema.ValidationError): __doc__ = _(u"Invalid email address")
class UnsubscribeNewsletterForm(extensible.ExtensibleForm, form.Form): fields = field.Fields(INewsletterUnsubscribe) ignoreContext = True id = "newsletter-unsubscriber-form" label = _( u'mailchimp_unsubscribe_newsletter_form_title', default=u"Unsubscribe from newsletter", ) description = _(u'mailchimp_unsubscribe_newsletter_form_description', default='') def updateFields(self): super(UnsubscribeNewsletterForm, self).updateFields() self.fields['interest_groups'].widgetFactory = CheckBoxFieldWidget def updateWidgets(self): super(UnsubscribeNewsletterForm, self).updateWidgets() registry = getUtility(IRegistry) self.mailchimp_settings = registry.forInterface(IMailchimpSettings) self.mailchimp = getUtility(IMailchimpLocator) # Set a given email address if self.request.get('email'): self.widgets['email'].value = self.request['email'] # Retrieve the list id either from the request/form or fall back to # the default_list setting. list_id = self.context.REQUEST.get('list_id') list_id = list_id or self.request.form.get('form.widgets.list_id') list_id = list_id or self.mailchimp_settings.default_list self.widgets['list_id'].mode = HIDDEN_MODE self.widgets['list_id'].value = list_id # Show/hide interest_groups widget self.available_interest_groups = self.mailchimp.groups(list_id=list_id) if not self.available_interest_groups: self.widgets['interest_groups'].mode = HIDDEN_MODE @button.buttonAndHandler( _(u"unsubscribe_newsletter_button", default=u"Unsubscribe"), name='unsubscribe', ) def handle_unsubscribe(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return list_id = data.get('list_id') or self.mailchimp.default_list_id() email = data['email'] update_data = {} if data.get('unsubscribe'): update_data['status'] = 'unsubscribed' else: interest_groups = {} if data.get('interest_groups'): for group in data.get('interest_groups', []): interest_groups[group] = False update_data['interests'] = interest_groups try: self.mailchimp.update_subscriber(list_id, email_address=email, **update_data) except MailChimpException as error: if error.code != 404: # If a subscriber did not exist we don't want to announce # it. Treat only != 404 as an error. IStatusMessage(self.request).addStatusMessage( _( u'mailchimp_unsubscribe_error_msg', default=u'We could not unsubscribe you from ' u'the newsletter. ' u"Please contact the site administrator: " u"'${error}'", mapping={u"error": error}, ), type="info", ) IStatusMessage(self.request).addStatusMessage( _( u'mailchimp_unsubscribed_msg', default=(u'Thank you. You have been unsubscribed from ' u'the Newsletter.'), ), type="info", ) portal = getSite() self.request.response.redirect(portal.absolute_url())
# -*- coding: utf-8 -*- from collective.mailchimp import _ from zope import schema from zope.interface import Interface from zope.interface import Invalid from zope.interface import invariant from zope.schema.vocabulary import SimpleTerm from zope.schema.vocabulary import SimpleVocabulary import re available_fields = SimpleVocabulary( [ SimpleTerm(value=u'subscriber_list', title=_(u'Subscriber list')), SimpleTerm(value=u'email', title=_(u'E-Mail')), ] ) class ICollectiveMailchimp(Interface): """Marker interface that defines a ZTK browser layer. We can reference this in the 'layer' attribute of ZCML <browser:* /> directives to ensure the relevant registration only takes effect when this theme is installed. The browser layer is installed via the browserlayer.xml GenericSetup import step. """ class NotAnEmailAddress(schema.ValidationError):
import re from zope import schema from zope.interface import Interface from zope.interface import invariant from zope.interface import Invalid from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm from collective.mailchimp import _ available_fields = SimpleVocabulary( [SimpleTerm(value=u"subscriber_list", title=_(u"Subscriber list")), SimpleTerm(value=u"email", title=_(u"E-Mail"))] ) class ICollectiveMailchimp(Interface): """Marker interface that defines a ZTK browser layer. We can reference this in the 'layer' attribute of ZCML <browser:* /> directives to ensure the relevant registration only takes effect when this theme is installed. The browser layer is installed via the browserlayer.xml GenericSetup import step. """ class NotAnEmailAddress(schema.ValidationError): __doc__ = _(u"Invalid email address") check_email = re.compile(r"[a-zA-Z0-9._%-]+@([a-zA-Z0-9-]+.)*[a-zA-Z]{2,4}").match
def handleApply(self, action): data, errors = self.extractData() if 'email' in data: mailchimp = getUtility(IMailchimpLocator) # Retrieve list_id either from a hidden field in the form or fetch # the first list from mailchimp. if 'list_id' in data: list_id = data['list_id'] else: list_id = mailchimp.default_list_id() # Groupings if 'interest_groups' in data: interest_grouping = mailchimp.groups(list_id=list_id) if interest_grouping and data['interest_groups']: data['groupings'] = [{ 'id': interest_grouping['id'], 'groups': ",".join(data['interest_groups']), }] # Use email_type if one is provided by the form, if not choose the # default email type from the control panel settings. if 'email_type' in data: email_type = data['email_type'] else: email_type = None # Subscribe to MailChimp list try: mailchimp.subscribe( list_id=list_id, email_address=data['email'], merge_vars=data, email_type=email_type, ) except MailChimpException, error: if error.code == 214: error_msg = _( u"mailchimp_error_msg_already_subscribed", default=u"Could not subscribe to newsletter. " u"The email '${email}' is already subscribed.", mapping={u"email": data['email']}) translated_error_msg = self.context.translate(error_msg) raise WidgetActionExecutionError( 'email', Invalid(translated_error_msg)) elif error.code == 220: error_msg = _( u"mailchimp_error_msg_banned", default=u"Could not subscribe to newsletter. " u"The email '${email}' has been banned.", mapping={u"email": data['email']}) translated_error_msg = self.context.translate(error_msg) raise WidgetActionExecutionError( 'email', Invalid(translated_error_msg)) else: error_msg = _( u"mailchimp_error_msg", default=u"Could not subscribe to newsletter. " u"Please contact the site administrator: " u"'${error}'", mapping={u"error": error}) translated_error_msg = self.context.translate(error_msg) raise ActionExecutionError(Invalid(translated_error_msg)) IStatusMessage(self.context.REQUEST).addStatusMessage( _(u"We have to confirm your email address. In order to " + u"finish the newsletter subscription, click on the link " + u"inside the email we just send you."), type="info") portal = getSite() self.request.response.redirect(portal.absolute_url())
class NewsletterSubscriberForm(extensible.ExtensibleForm, form.Form): fields = field.Fields(INewsletterSubscribe) ignoreContext = True id = "newsletter-subscriber-form" label = _(u"Subscribe to newsletter") def updateActions(self): super(NewsletterSubscriberForm, self).updateActions() self.actions['subscribe'].addClass('context') def updateFields(self): super(NewsletterSubscriberForm, self).updateFields() self.fields['interest_groups'].widgetFactory = \ CheckBoxFieldWidget self.fields['email_type'].widgetFactory = \ RadioFieldWidget def updateWidgets(self): super(NewsletterSubscriberForm, self).updateWidgets() # Show/hide mail format option widget registry = getUtility(IRegistry) mailchimp_settings = registry.forInterface(IMailchimpSettings) if not mailchimp_settings.email_type_is_optional: self.widgets['email_type'].mode = HIDDEN_MODE # Retrieve the list id either from the request/form or fall back to # the default_list setting. if 'list_id' in self.context.REQUEST: list_id = self.context.REQUEST['list_id'] elif 'form.widgets.list_id' in self.request.form: list_id = self.request.form['form.widgets.list_id'] else: list_id = mailchimp_settings.default_list self.widgets['list_id'].mode = HIDDEN_MODE self.widgets['list_id'].value = list_id # Show/hide interest_groups widget mailchimp = getUtility(IMailchimpLocator) groups = mailchimp.groups(list_id=list_id) if not groups: self.widgets['interest_groups'].mode = HIDDEN_MODE if 'preselect_group' in self.context.REQUEST: for group_index in self.request['preselect_group']: group_index = int(group_index) self.widgets['interest_groups']\ .items[group_index]['checked'] = True @button.buttonAndHandler(_(u"subscribe_to_newsletter_button", default=u"Subscribe"), name='subscribe') def handleApply(self, action): data, errors = self.extractData() if 'email' not in data: return mailchimp = getUtility(IMailchimpLocator) # Retrieve list_id either from a hidden field in the form or fetch # the first list from mailchimp. if 'list_id' in data and data['list_id'] is not None: list_id = data['list_id'] else: list_id = mailchimp.default_list_id() # Groupings interests = {} if 'interest_groups' in data and data['interest_groups'] is not None: interest_grouping = mailchimp.groups(list_id=list_id) if interest_grouping and data['interest_groups']: # Create dictionary with as keys the interest groups, and as # values always True. interests = dict.fromkeys(data['interest_groups'], True) # Use email_type if one is provided by the form, if not choose the # default email type from the control panel settings. if 'email_type' in data: email_type = data['email_type'] else: email_type = 'HTML' # Subscribe to MailChimp list try: mailchimp.subscribe( list_id=list_id, email_address=data['email'], email_type=email_type, interests=interests ) except MailChimpException as error: return self.handle_error(error, data) registry = getUtility(IRegistry) mailchimp_settings = registry.forInterface(IMailchimpSettings) if mailchimp_settings.double_optin: message = _( u"We have to confirm your email address. In order to " + u"finish the newsletter subscription, click on the link " + u"inside the email we just send you.") else: message = _( u"You have been subscribed to our newsletter succesfully.") IStatusMessage(self.context.REQUEST).addStatusMessage( message, type="info") portal = getSite() self.request.response.redirect(portal.absolute_url()) def handle_error(self, error, data): # Current api v3 documentation only lists errors in the 400 and 500 # range. The 400 code can mean a lot of things... if error.code == 400: error_msg = _( u"mailchimp_error_msg_already_subscribed", default=u"Could not subscribe to newsletter. " u"Either the email '${email}' is already subscribed " u"or something else is wrong. Try again later.", mapping={u"email": data['email']}) translated_error_msg = self.context.translate(error_msg) raise WidgetActionExecutionError( 'email', Invalid(translated_error_msg) ) elif error.code == 220: error_msg = _( u"mailchimp_error_msg_banned", default=u"Could not subscribe to newsletter. " u"The email '${email}' has been banned.", mapping={u"email": data['email']}) translated_error_msg = self.context.translate(error_msg) raise WidgetActionExecutionError( 'email', Invalid(translated_error_msg) ) else: error_msg = _( u"mailchimp_error_msg", default=u"Could not subscribe to newsletter. " u"Please contact the site administrator: " u"'${error}'", mapping={u"error": error}) translated_error_msg = self.context.translate(error_msg) raise ActionExecutionError( Invalid(translated_error_msg) )