Beispiel #1
0
class NewEmailForm(Form):
    to = StringField(validators=[
        DataRequired(i8n.EMAIL_TO_REQUIRED),
        Emails(AppConfig.EMAIL_ADDRESS_DELIMITER, i8n.EMAIL_ADDRESS_INVALID)
    ])

    cc = StringField(validators=[
        DataOptional(),
        Emails(AppConfig.EMAIL_ADDRESS_DELIMITER, i8n.EMAIL_ADDRESS_INVALID)
    ])

    bcc = StringField(validators=[
        DataOptional(),
        Emails(AppConfig.EMAIL_ADDRESS_DELIMITER, i8n.EMAIL_ADDRESS_INVALID)
    ])

    subject = StringField(validators=[DataOptional()])

    body = HtmlTextAreaField(validators=[DataOptional()])

    attachments = FileField(validators=[DataOptional()],
                            render_kw={'multiple': True})

    submit = SubmitField()

    def as_dict(self, attachment_encoder: AttachmentEncoder) -> dict:
        attachments = request.files.getlist(self.attachments.name)
        form = {key: value for (key, value) in self.data.items() if value}
        form.pop('submit', None)
        form['sent_at'] = None
        form['read'] = True
        form['from'] = current_user.email
        form['to'] = _split_emails(form.get('to'))
        form['cc'] = _split_emails(form.get('cc'))
        form['bcc'] = _split_emails(form.get('bcc'))
        form['body'] = form.get('body')
        form['attachments'] = list(
            _attachments_as_dict(attachments, attachment_encoder))
        return form

    def _populate(self, email: dict):
        pass

    @classmethod
    def _new_instance_for(cls, action_name: Optional[str]):
        if not action_name:
            return cls(request.form)

        try:
            clazz = next(clazz for clazz in NewEmailForm.__subclasses__()
                         if getattr(clazz, 'action_name', None) == action_name)
        except StopIteration:
            return None
        else:
            return clazz(request.form)

    @classmethod
    def from_request(cls, email_store: EmailStore):
        action_name = request.args.get('action')
        form = cls._new_instance_for(action_name)
        if not form:
            return None

        uid = request.args.get('uid')
        if uid:
            reference = email_store.get(uid)
            if not reference or not current_user.can_access(reference):
                return None
            form._populate(reference)

        return form
Beispiel #2
0
 def verify(cls, delimiter, field_value):
     validator = Emails(delimiter)
     validator(form=None, field=DummyField(field_value))
Beispiel #3
0
class NewEmailForm(FlaskForm):
    to = StringField(validators=[
        DataRequired(i8n.EMAIL_TO_REQUIRED),
        Emails(AppConfig.EMAIL_ADDRESS_DELIMITER, i8n.EMAIL_ADDRESS_INVALID),
    ])

    cc = StringField(validators=[
        DataOptional(),
        Emails(AppConfig.EMAIL_ADDRESS_DELIMITER, i8n.EMAIL_ADDRESS_INVALID),
    ])

    bcc = StringField(validators=[
        DataOptional(),
        Emails(AppConfig.EMAIL_ADDRESS_DELIMITER, i8n.EMAIL_ADDRESS_INVALID),
    ])

    subject = StringField(validators=[DataOptional()])

    body = HtmlTextAreaField(validators=[
        DataOptional(),
    ])

    forwarded_attachments = SelectMultipleField(choices=[],
                                                validators=[
                                                    DataOptional(),
                                                ])

    attachments = FileField(validators=[
        DataOptional(),
    ],
                            render_kw={
                                'multiple': True,
                            })

    submit = SubmitField()

    def as_dict(self, email_store: EmailStore) -> dict:
        form = {key: value for (key, value) in self.data.items() if value}
        form.pop('submit', None)

        attachments = request.files.getlist(self.attachments.name)
        to = _split_emails(form.get('to'))
        cc = _split_emails(form.get('cc'))
        bcc = _split_emails(form.get('bcc'))

        sent_at = None
        if all(_is_local_message(address) for address in chain(to, cc, bcc)):
            sent_at = datetime.utcnow().strftime('%Y-%m-%d %H:%M')

        form['sent_at'] = sent_at
        form['read'] = True
        form['from'] = current_user.email
        form['to'] = to
        form['cc'] = cc
        form['bcc'] = bcc
        form['body'] = form.get('body')
        form['subject'] = form.get('subject', i8n.EMAIL_NO_SUBJECT)
        form['attachments'] = list(_attachments_as_dict(attachments))
        return form

    def _populate(self, user, email_store: EmailStore):
        pass

    @classmethod
    def _new_instance_for(cls, action_name: Optional[str]):
        if not action_name:
            return cls(request.form)

        try:
            clazz = next(clazz for clazz in NewEmailForm.__subclasses__()
                         if getattr(clazz, 'action_name', None) == action_name)
        except StopIteration:
            return None
        else:
            return clazz(request.form)

    def _get_reference_email(self, email_store: EmailStore) -> Optional[dict]:
        uid = request.args.get('uid', '')
        if not uid:
            return None

        reference = email_store.get(uid)
        if not self._can_access(current_user, reference):
            return None

        return reference

    @classmethod
    def _can_access(cls, user, email: dict) -> bool:
        actors = set()
        actors.add(email.get('from'))
        actors.update(email.get('to', []))
        actors.update(email.get('cc', []))
        actors.update(email.get('bcc', []))

        return user.email in actors

    @classmethod
    def from_request(cls, user, email_store: EmailStore):
        action_name = request.args.get('action')
        form = cls._new_instance_for(action_name)
        if not form:
            return None

        form._populate(user, email_store)

        return form