def sendMail(context, parent=None, run=True, transactional=True):
  """Sends out an email using context to supply the needed information.

  Args:
    context: The context supplied to the email message (dictionary)
    parent: The parent entity to use for when this mail is to be sent in a
            transaction.
    run: If true the mail will be sent otherwise the function that can sent
         the mail will be returned.
    transactional: Whether the task should be created transactionally.

  Raises:
    Error that corresponds with the first problem it finds iff the message
    is not properly initialized.

    List of all possible errors:
      http://code.google.com/appengine/docs/mail/exceptions.html
  """
  # construct the EmailMessage from the given context
  message = mail.EmailMessage(**context)
  message.check_initialized()

  # don't send out emails in non-local debug mode
  if not system.isLocal() and system.isDebug():
    return

  txn = mailer.getSpawnMailTaskTxn(
      context=context, parent=parent, transactional=transactional)
  if run:
    return db.RunInTransaction(txn)
  else:
    return txn
 def create_comment_txn():
     comment = comment_form.create(commit=True,
                                   parent=data.url_proposal)
     context = notifications.newReviewContext(data, comment, to_emails)
     sub_txn = mailer.getSpawnMailTaskTxn(context, parent=comment)
     sub_txn()
     return comment
def sendMail(context, parent=None, run=True, transactional=True):
    """Sends out an email using context to supply the needed information.

  Args:
    context: The context supplied to the email message (dictionary)
    parent: The parent entity to use for when this mail is to be sent in a
            transaction.
    run: If true the mail will be sent otherwise the function that can sent
         the mail will be returned.
    transactional: Whether the task should be created transactionally.

  Raises:
    Error that corresponds with the first problem it finds iff the message
    is not properly initialized.

    List of all possible errors:
      http://code.google.com/appengine/docs/mail/exceptions.html
  """
    # construct the EmailMessage from the given context
    message = mail.EmailMessage(**context)
    message.check_initialized()

    # don't send out emails in non-local debug mode
    if not system.isLocal() and system.isDebug():
        return

    txn = mailer.getSpawnMailTaskTxn(context=context,
                                     parent=parent,
                                     transactional=transactional)
    if run:
        return db.RunInTransaction(txn)
    else:
        return txn
Exemple #4
0
      def reject_request_txn():
        request = db.get(self.data.request_entity.key())
        request.status = 'rejected'
        request.put()

        context = notifications.handledRequestContext(self.data, request.status)
        sub_txn = mailer.getSpawnMailTaskTxn(context, parent=request)
        sub_txn()
Exemple #5
0
    def withdraw_invite_txn():
      invite = db.get(invite_key)
      invite.status = 'withdrawn'
      invite.put()

      context = notifications.handledInviteContext(self.data)
      sub_txn = mailer.getSpawnMailTaskTxn(context, parent=invite)
      sub_txn()
Exemple #6
0
  def txn():
    record = db.get(record_key)
    record.status = new_status
    record.put()

    if context:
      sub_txn = mailer.getSpawnMailTaskTxn(context, parent=record)
      sub_txn()
Exemple #7
0
  def resubmit_invite_txn():
    invite = db.get(invite_key)
    invite.status = 'pending'
    invite.put()

    context = notifications.handledInviteContext(request_data)
    sub_txn = mailer.getSpawnMailTaskTxn(context, parent=invite)
    sub_txn()
Exemple #8
0
def sendFirstTaskConfirmationTxn(profile, task):
    """Returns a transaction which sends a confirmation email to a student who
  completes their first task.
  """

    if not profile.is_student:
        raise ValueError('Only students can be queried for closed tasks.')

    context = notifications.getFirstTaskConfirmationContext(profile)
    return mailer.getSpawnMailTaskTxn(context, parent=task)
Exemple #9
0
def sendFirstTaskConfirmationTxn(profile, task):
  """Returns a transaction which sends a confirmation email to a student who
  completes their first task.
  """

  if not profile.student_info:
    raise ValueError('Only students can be queried for closed tasks.')
  
  context = notifications.getFirstTaskConfirmationContext(profile)
  return mailer.getSpawnMailTaskTxn(context, parent=task)
Exemple #10
0
    def update_proposal_txn():
      proposal = db.get(proposal_key)
      proposal_form.instance = proposal
      proposal = proposal_form.save(commit=True)

      context = notifications.updatedProposalContext(self.data, proposal, to_emails)
      sub_txn = mailer.getSpawnMailTaskTxn(context, parent=proposal)
      sub_txn()

      return proposal
Exemple #11
0
        def update_proposal_txn():
            proposal = db.get(proposal_key)
            proposal_form.instance = proposal
            proposal = proposal_form.save(commit=True)

            context = notifications.updatedProposalContext(
                data, proposal, to_emails)
            sub_txn = mailer.getSpawnMailTaskTxn(context, parent=proposal)
            sub_txn()

            return proposal
Exemple #12
0
    def create_proposal_trx():
      student_info = db.get(student_info_key)
      student_info.number_of_proposals += 1
      student_info.put()

      proposal = proposal_form.create(commit=True, parent=self.data.profile)

      context = notifications.newProposalContext(self.data, proposal, to_emails)
      sub_txn = mailer.getSpawnMailTaskTxn(context, parent=proposal)
      sub_txn()

      return proposal
Exemple #13
0
      def accept_request_txn():
        request = db.get(request_key)
        self.data.requester_profile = profile = db.get(profile_key)

        request.status = 'accepted'
        profile.is_mentor = True
        profile.mentor_for.append(organization_key)
        profile.mentor_for = list(set(profile.mentor_for))

        profile.put()
        request.put()

        context = notifications.handledRequestContext(self.data, request.status)
        sub_txn = mailer.getSpawnMailTaskTxn(context, parent=request)
        sub_txn()
Exemple #14
0
        def create_proposal_trx():
            profile = data.ndb_profile.key.get()
            profile.student_data.number_of_proposals += 1
            profile.put()

            proposal = GSoCProposal(parent=data.ndb_profile.key.to_old_key(),
                                    **proposal_properties)
            proposal.put()

            context = notifications.newProposalContext(data, proposal,
                                                       to_emails)
            sub_txn = mailer.getSpawnMailTaskTxn(context, parent=proposal)
            sub_txn()

            return proposal
Exemple #15
0
    def create_proposal_trx():
      profile = data.ndb_profile.key.get()
      profile.student_data.number_of_proposals += 1
      profile.put()

      proposal = GSoCProposal(
          parent=data.ndb_profile.key.to_old_key(),
          **proposal_properties)
      proposal.put()

      context = notifications.newProposalContext(data, proposal, to_emails)
      sub_txn = mailer.getSpawnMailTaskTxn(context, parent=proposal)
      sub_txn()

      return proposal
Exemple #16
0
        def accept_request_txn():
            request = db.get(request_key)
            profile = db.get(profile_key)

            request.status = "accepted"
            profile.is_mentor = True
            profile.mentor_for.append(organization_key)
            profile.mentor_for = list(set(profile.mentor_for))

            profile.put()
            request.put()

            context = notifications.handledRequestContext(self.data, request.status)
            sub_txn = mailer.getSpawnMailTaskTxn(context, parent=request)
            # TODO(SRabbelier): just call as soon as we make User Request's parent
            db.run_in_transaction(sub_txn)
Exemple #17
0
def notifyParticipantsOfMessage(message, is_reply):
  """Notifies participants in a conversation's participants of a new message.

  Args:
    message: Key (ndb) of GCIMessage of which to notify participants.
    is_reply: Whether this message is a reply to an existing conversation.
  """
  message_ent = message.get()
  conversation_ent = message_ent.conversation.get()

  to_emails = getSubscribedEmails(
      message_ent.conversation, exclude=[message_ent.author])

  context = notifications.getTaskConversationMessageContext(
      message, list(to_emails), is_reply)

  txn = mailer.getSpawnMailTaskTxn(context, parent=None)
  db.run_in_transaction(txn)
Exemple #18
0
def notifyParticipantsOfMessage(message, is_reply):
    """Notifies participants in a conversation's participants of a new message.

  Args:
    message: Key (ndb) of GCIMessage of which to notify participants.
    is_reply: Whether this message is a reply to an existing conversation.
  """
    message_ent = message.get()
    conversation_ent = message_ent.conversation.get()

    to_emails = getSubscribedEmails(message_ent.conversation,
                                    exclude=[message_ent.author])

    context = notifications.getTaskConversationMessageContext(
        message, list(to_emails), is_reply)

    txn = mailer.getSpawnMailTaskTxn(context, parent=None)
    db.run_in_transaction(txn)
Exemple #19
0
    def create_or_update_slot_transfer_trx():
      update = False
      if slot_transfer_entity:
        slot_transfer = db.get(slot_transfer_entity.key())
        slot_transfer_form.instance = slot_transfer
        slot_transfer = slot_transfer_form.save(commit=True)

        update = True
      else:
        slot_transfer = slot_transfer_form.create(
            commit=True, parent=data.url_ndb_org.key.to_old_key())

      context = notifications.createOrUpdateSlotTransferContext(
          data, slot_transfer, to_emails, update)
      sub_txn = mailer.getSpawnMailTaskTxn(
          context, parent=slot_transfer.parent())
      sub_txn()

      return slot_transfer
Exemple #20
0
        def create_or_update_slot_transfer_trx():
            update = False
            if slot_transfer_entity:
                slot_transfer = db.get(slot_transfer_entity.key())
                slot_transfer_form.instance = slot_transfer
                slot_transfer = slot_transfer_form.save(commit=True)

                update = True
            else:
                slot_transfer = slot_transfer_form.create(
                    commit=True, parent=data.url_ndb_org.key.to_old_key())

            context = notifications.createOrUpdateSlotTransferContext(
                data, slot_transfer, to_emails, update)
            sub_txn = mailer.getSpawnMailTaskTxn(context,
                                                 parent=slot_transfer.parent())
            sub_txn()

            return slot_transfer
Exemple #21
0
def storeAndNotifyTxn(comment, task=None):
    """Returns a method to be run in a transaction to notify subscribers.

  Args:
    comment: A GCIComment instance
    task: optional GCITask instance that is the parent of the specified comment
  """
    if not task:
        task = comment.parent()
    elif task.key() != comment.parent_key():
        raise ValueError(
            "The specified task must be the parent of the comment")

    if comment_model.GCIComment.created_by.get_value_for_datastore(comment):
        author_key = ndb.Key.from_old_key(
            comment_model.GCIComment.created_by.get_value_for_datastore(
                comment))
    else:
        author_key = None

    to_emails = []
    profiles = ndb.get_multi(map(ndb.Key.from_old_key, task.subscribers))
    for profile in profiles:
        if profile and ((not author_key)
                        or profile.key.parent() != author_key):
            to_emails.append(profile.contact.email)

    # Send out an email to an entire organization when set.
    org = task.org
    if org.notification_mailing_list:
        to_emails.append(org.notification_mailing_list)

    context = notifications.getTaskCommentContext(task, comment, to_emails)
    sub_txn = mailer.getSpawnMailTaskTxn(context, parent=task)

    def txn():
        sub_txn()
        comment.put()

    return txn
Exemple #22
0
def storeAndNotifyTxn(comment, task=None):
  """Returns a method to be run in a transaction to notify subscribers.

  Args:
    comment: A GCIComment instance
    task: optional GCITask instance that is the parent of the specified comment
  """
  if not task:
    task = comment.parent()
  elif task.key() != comment.parent_key():
    raise ValueError("The specified task must be the parent of the comment")

  if comment_model.GCIComment.created_by.get_value_for_datastore(comment):
    author_key = ndb.Key.from_old_key(
        comment_model.GCIComment.created_by.get_value_for_datastore(comment))
  else:
    author_key = None

  to_emails = []
  profiles = ndb.get_multi(map(ndb.Key.from_old_key, task.subscribers))
  for profile in profiles:
    if profile and ((not author_key) or profile.key.parent() != author_key):
      to_emails.append(profile.contact.email)

  # Send out an email to an entire organization when set.
  org = task.org
  if org.notification_mailing_list:
    to_emails.append(org.notification_mailing_list)

  context = notifications.getTaskCommentContext(task, comment, to_emails)
  sub_txn = mailer.getSpawnMailTaskTxn(context, parent=task)
  def txn():
    sub_txn()
    comment.put()

  return txn
Exemple #23
0
 def create_comment_txn():
     comment = comment_form.create(commit=True, parent=self.data.proposal)
     context = notifications.newCommentContext(self.data, comment, to_emails)
     sub_txn = mailer.getSpawnMailTaskTxn(context, parent=comment)
     sub_txn()
     return comment
Exemple #24
0
def setStatus(organization,
              program,
              site,
              program_messages,
              new_status,
              linker=None,
              url_names=None,
              org_admins=None):
    """Sets status of the specified organization.

  This function may be called to accept the organization into the program
  or rejected it from the program, if new status is set to ACCEPTED or REJECTED,
  respectively. If the optional list of organization administrators
  is specified along with the program specific messages, they will be sent
  acceptance or rejection message.

  Additionally, if the organization status is set to ACCEPTED and the optional
  list of organization administrators is specified along with the program
  specific messages, the administrators will be sent the organization member
  welcome message.

  Args:
    organization: Organization entity.
    program: Program entity to which organization is assigned.
    site: Site entity.
    program_messages: ProgramMessages entity that holds the message
          templates provided by the program admins.
    new_status: New status of the organization. Must be one of
      org_model.Status constants.
    linker: Instance of links.Linker class (Optional: required only for
      sending notifications).
    url_names: Instance of url_names.UrlNames (Optional: required only for
      sending notifications).
    org_admins: Optional list of organization administrators for the specified
      organization.

  Returns:
    The updated organization entity.
  """
    if organization.status != new_status:
        organization.status = new_status
        organization.put()

        if (org_admins and new_status
                in [org_model.Status.ACCEPTED, org_model.Status.REJECTED]):

            # recipients of organization acceptance or rejection email
            recipients = [org_admin.contact.email for org_admin in org_admins]

            if new_status == org_model.Status.ACCEPTED:
                if not (linker and url_names):
                    raise ValueError(DEF_LINKER_URL_NAMES_REQUIRED)

                notification_context = (
                    notifications.OrganizationAcceptedContextProvider(
                        linker,
                        url_names).getContext(recipients, organization,
                                              program, site, program_messages))

                # organization administrators are also sent the welcome email
                for org_admin in org_admins:
                    if (profile_model.MessageType.ORG_MEMBER_WELCOME_MSG
                            not in org_admin.sent_messages):
                        profile_logic.dispatchOrgMemberWelcomeEmail(
                            org_admin,
                            program,
                            program_messages,
                            site,
                            parent=organization)
            elif new_status == org_model.Status.REJECTED:
                notification_context = (
                    notifications.OrganizationRejectedContextProvider(
                    ).getContext(recipients, organization, program, site,
                                 program_messages))

            sub_txn = mailer.getSpawnMailTaskTxn(notification_context,
                                                 parent=organization)
            sub_txn()

    return organization
Exemple #25
0
 def create_invite_txn():
   invite = invite_form.create(commit=True)
   context = notifications.inviteContext(self.data, invite)
   sub_txn = mailer.getSpawnMailTaskTxn(context, parent=invite)
   sub_txn()
   return invite
Exemple #26
0
 def create_request_txn():
   request = request_form.create(commit=True)
   context = notifications.requestContext(self.data, request, admin_emails)
   sub_txn = mailer.getSpawnMailTaskTxn(context, parent=request)
   sub_txn()
   return request
Exemple #27
0
def setStatus(organization, program, site, program_messages,
              new_status, linker=None, url_names=None, org_admins=None):
  """Sets status of the specified organization.

  This function may be called to accept the organization into the program
  or rejected it from the program, if new status is set to ACCEPTED or REJECTED,
  respectively. If the optional list of organization administrators
  is specified along with the program specific messages, they will be sent
  acceptance or rejection message.

  Additionally, if the organization status is set to ACCEPTED and the optional
  list of organization administrators is specified along with the program
  specific messages, the administrators will be sent the organization member
  welcome message.

  Args:
    organization: Organization entity.
    program: Program entity to which organization is assigned.
    site: Site entity.
    program_messages: ProgramMessages entity that holds the message
          templates provided by the program admins.
    new_status: New status of the organization. Must be one of
      org_model.Status constants.
    linker: Instance of links.Linker class (Optional: required only for
      sending notifications).
    url_names: Instance of url_names.UrlNames (Optional: required only for
      sending notifications).
    org_admins: Optional list of organization administrators for the specified
      organization.

  Returns:
    The updated organization entity.
  """
  if organization.status != new_status:
    organization.status = new_status
    organization.put()

    if (org_admins and
        new_status in [org_model.Status.ACCEPTED, org_model.Status.REJECTED]):

      # recipients of organization acceptance or rejection email
      recipients = [org_admin.contact.email for org_admin in org_admins]

      if new_status == org_model.Status.ACCEPTED:
        if not (linker and url_names):
          raise ValueError(DEF_LINKER_URL_NAMES_REQUIRED)

        notification_context = (
            notifications.OrganizationAcceptedContextProvider(linker,
                                                              url_names)
                .getContext(
                    recipients, organization, program, site,
                    program_messages))

        # organization administrators are also sent the welcome email
        for org_admin in org_admins:
          if (profile_model.MessageType.ORG_MEMBER_WELCOME_MSG
              not in org_admin.sent_messages):
            profile_logic.dispatchOrgMemberWelcomeEmail(
                org_admin, program, program_messages, site, parent=organization)
      elif new_status == org_model.Status.REJECTED:
        notification_context = (
            notifications.OrganizationRejectedContextProvider()
                .getContext(
                    recipients, organization, program, site,
                    program_messages))

      sub_txn = mailer.getSpawnMailTaskTxn(
          notification_context, parent=organization)
      sub_txn()

  return organization