def __init__(self, method="post", action=None, enctype=None, use_tokens=True, **attrs): if method not in ("post", "get"): raise ValueError("Form method must be 'post' or 'get', " "not %r" % method) self.method = method self.action = action or self._get_default_action() if "class" not in attrs: attrs["class"] = "quixote" self.attrs = attrs self.widgets = [] self.submit_widgets = [] self.hidden_widgets = [] self._names = {} if enctype is not None and enctype not in ("application/x-www-form-urlencoded", "multipart/form-data"): raise ValueError, ( "Form enctype must be " "'application/x-www-form-urlencoded' or " "'multipart/form-data', not %r" % enctype ) self.enctype = enctype if use_tokens and self.method == "post": config = get_publisher().config if config.form_tokens: # unique token for each form, this prevents many cross-site # attacks and prevents a form from being submitted twice self.add(FormTokenWidget, self.TOKEN_NAME, value=None)
def _set_cookie(self, value, **attrs): """(session_id : string) Ensure that a session cookie with value 'session_id' will be returned to the client via the response object. Since Mod_Python has its own Cookie management system, we use it. """ config = get_publisher().config name = config.session_cookie_name domain = config.session_cookie_domain if config.session_cookie_path: path = config.session_cookie_path else: path = get_request().get_environ('SCRIPT_NAME') if not path.endswith("/"): path += "/" expires = -1 options = {'expires': expires, 'path': path } if domain is not None: options.update({'domain':domain}) if value: Cookie.add_cookie(self.modpython_request, name, value, **options) return name
def _q_lookup(self, component): user_mgr = get_publisher().context.user_mgr if user_mgr.has_user(component): return BookmarksDirectory(component) else: return None
def t(text): """Return translated text. This is a standard hook to gettext, but with a twist: since our Quixote app runs in an app server, the typical global gettext approach doesn't work, because requests come in from different users and languages. We therefore have to check the HTTPRequest object to find the appropriate translator. """ publisher = get_publisher() if not publisher: return text try: request = get_request() except AttributeError: # publisher has no request during import/load of this module return text if not request or not hasattr(request, 'gettext'): # gettext attr is installed by QonPublisher return text return request.gettext(text)
def get_session(self): """() -> Session Fetch or create a session object for the current session, and return it. If a session cookie is found in the HTTP request object, use it to look up and return an existing session object. If no session cookie is found, create a new session. Note that this method does *not* cause the new session to be stored in the session manager, nor does it drop a session cookie on the user. Those are both the responsibility of finish_successful_request(). """ config = get_publisher().config id = self._get_session_id(config) session = None if id: session = self.store.load_session(id) if session is None: session = self._create_session() #session._set_access_time(self.ACCESS_TIME_RESOLUTION) return session
def __init__(self, method="post", action=None, enctype=None, use_tokens=True, **attrs): if method not in ("post", "get"): raise ValueError("Form method must be 'post' or 'get', " "not %r" % method) self.method = method self.action = action or self._get_default_action() if 'class' not in attrs: attrs['class'] = 'quixote' self.attrs = attrs self.widgets = [] self.submit_widgets = [] self.hidden_widgets = [] self._names = {} if enctype is not None and enctype not in ( "application/x-www-form-urlencoded", "multipart/form-data"): raise ValueError, ("Form enctype must be " "'application/x-www-form-urlencoded' or " "'multipart/form-data', not %r" % enctype) self.enctype = enctype if use_tokens and self.method == "post": config = get_publisher().config if config.form_tokens: # unique token for each form, this prevents many cross-site # attacks and prevents a form from being submitted twice self.add(FormTokenWidget, self.TOKEN_NAME, value=None)
def process(self, env): request = HTTPRequest(self.rfile, env) response = get_publisher().process_request(request) try: self.send_response(response.get_status_code(), response.get_reason_phrase()) response.write(self.wfile, include_status=False) except IOError, err: print "IOError while sending response ignored: %s" % err
def streamer(request=request, visibility=visibility, files=files, self=self): quixote.get_publisher()._set_request(request) r = page.pre(request, 'Uploading pictures', 'uploading', trail=False) r += H('<H1>Uploading pictures...</H1>\n') r += H('<dl>\n') yield str(r) for f in files: for y in self.do_upload_file(f.fp, f.base_filename, None, visibility): yield y r += H('</dl>\n') r += H('<p><a href="%s">Upload more pictures</a>\n') % self.path() r += page.post() yield str(r)
def _process(rfile, env, include_body): """Process a single request, in background Quixote thread.""" request = HTTPRequest(rfile, env, seekable=True) response = get_publisher().process_request(request) status, reason = response.get_status_code(), response.get_reason_phrase() # write response body to temporary file, this ensures that write() runs in # the correct thread and we are not blocked by slow clients. body = tempfile.SpooledTemporaryFile() response.write(body, include_status=False, include_body=include_body) body.seek(0) return (status, reason, body)
def watchable_seen(self): """Call this when user sees object""" if not self.watchable(): return if get_publisher() is None: return user = get_user() if user is None: return if hasattr(user, 'get_watch_list'): user.get_watch_list().watchable_seen(self)
def process(self, env, include_body=True): response = get_publisher().process(self.rfile, env) if self.protocol_version == 'HTTP/1.1': # single threaded server, persistent connections will block others response.set_header('connection', 'close') try: self.send_response(response.get_status_code(), response.get_reason_phrase()) self.flush_headers() response.write(self.wfile, include_status=False, include_body=include_body) except IOError as err: print("IOError while sending response ignored: %s" % err)
def closed_and_paid(context, form_id): url = "{}/portail-parent/aes-inscrire-mon-enfant-a-une-plaine/{}/jump/trigger/closed_and_paid".format( context.get("site_url"), form_id ) orig = site_url.replace("https://","").replace("http://","") key = get_publisher().get_site_option(orig, 'api-secrets') url = sign_url( url, key, orig=orig, ) requests.post(url)
def process(self, env, include_body=True): response = get_publisher().process(self.rfile, env) if self.protocol_version == 'HTTP/1.1': # single threaded server, persistent connections will block others response.set_header('connection', 'close') try: self.send_response(response.get_status_code(), response.get_reason_phrase()) response.write(self.wfile, include_status=False, include_body=include_body) except IOError, err: print "IOError while sending response ignored: %s" % err
def close_plaines_reservation(context, form_id): url = "{}/portail-parent/aes-inscrire-mon-enfant-a-une-plaine/{}/jump/trigger/cloture".format( context.get("site_url"), form_id ) orig = site_url.replace("https://","").replace("http://","") key = get_publisher().get_site_option(orig, 'api-secrets') url = sign_url( url, key, orig=orig, ) # print ("{} {} - {} {}".format(first_date, first_date_other_demand, last_date, last_date_other_demand)) requests.post(url)
def _set_cookie(self, value, **attrs): config = get_publisher().config name = config.session_cookie_name if config.session_cookie_path: path = config.session_cookie_path else: path = get_request().get_environ('SCRIPT_NAME') if not path.endswith("/"): path += "/" domain = config.session_cookie_domain get_response().set_cookie(name, value, domain=domain, path=path, **attrs) return name
def has_session_cookie(self, must_exist=False): """(must_exist : boolean = false) -> bool Return true if the request already has a cookie identifying a session object. If 'must_exist' is true, the cookie must correspond to a currently existing session; otherwise (the default), we just check for the existence of the session cookie and don't inspect its content at all. """ config = get_publisher().config id = get_cookie(config.session_cookie_name) if id is None: return False if must_exist: return self.has_session(id) else: return True
def get_session(self): """() -> Session Fetch or create a session object for the current session, and return it. If a session cookie is found in the HTTP request object, use it to look up and return an existing session object. If no session cookie is found, create a new session. Note that this method does *not* cause the new session to be stored in the session manager, nor does it drop a session cookie on the user. Those are both the responsibility of maintain_session(), called at the end of a request. """ config = get_publisher().config id = self._get_session_id(config) session = self.get(id) or self._create_session() session._set_access_time(self.ACCESS_TIME_RESOLUTION) return session
def get_session(self, request): """get_session(request : HTTPRequest) -> Session Fetch or create a session object for the current session, and return it. If a session cookie is found in the HTTP request object 'request', use it to look up and return an existing session object. If no session cookie is found, create a new session. If the session cookie refers to a non-existent session, raise SessionError. If the check_session_addr config variable is true, then a mismatch between the IP address stored in an existing session the IP address of the current request also causes SessionError. Note that this method does *not* cause the new session to be stored in the session manager, nor does it drop a session cookie on the user. Those are both the responsibility of maintain_session(), called at the end of a request. """ config = get_publisher().config id = self._get_session_id(request, config) if id is not None: session = self.get(id) if session is None: # Note that it's important to revoke the session cookie # so the user doesn't keep getting "Expired session ID" # error pages. However, it has to be done in the # response object for the error document, which doesn't # exist yet. Thus, the code that formats SessionError # exceptions -- SessionError.format() by default -- is # responsible for revoking the session cookie. Yuck. raise SessionError(session_id=id) if (config.check_session_addr and session.get_remote_address() != request.get_environ("REMOTE_ADDR")): raise SessionError( "Remote IP address does not match the " "IP address that created the session", session_id=id) if id is None or session is None: # Generate a session ID and create the session. session = self._create_session(request) session._set_access_time(self.ACCESS_TIME_RESOLUTION) return session
def get_session(self, request): """get_session(request : HTTPRequest) -> Session Fetch or create a session object for the current session, and return it. If a session cookie is found in the HTTP request object 'request', use it to look up and return an existing session object. If no session cookie is found, create a new session. If the session cookie refers to a non-existent session, raise SessionError. If the check_session_addr config variable is true, then a mismatch between the IP address stored in an existing session the IP address of the current request also causes SessionError. Note that this method does *not* cause the new session to be stored in the session manager, nor does it drop a session cookie on the user. Those are both the responsibility of maintain_session(), called at the end of a request. """ config = get_publisher().config id = self._get_session_id(request, config) if id is not None: session = self.get(id) if session is None: # Note that it's important to revoke the session cookie # so the user doesn't keep getting "Expired session ID" # error pages. However, it has to be done in the # response object for the error document, which doesn't # exist yet. Thus, the code that formats SessionError # exceptions -- SessionError.format() by default -- is # responsible for revoking the session cookie. Yuck. raise SessionError(session_id=id) if (config.check_session_addr and session.get_remote_address() != request.get_environ("REMOTE_ADDR")): raise SessionError("Remote IP address does not match the " "IP address that created the session", session_id=id) if id is None or session is None: # Generate a session ID and create the session. session = self._create_session(request) session._set_access_time(self.ACCESS_TIME_RESOLUTION) return session
def __init__(self, method="post", enctype=None, use_tokens=1): if method not in ("post", "get"): raise ValueError("Form method must be 'post' or 'get', " "not %r" % method) self.method = method if enctype is not None and enctype not in ( "application/x-www-form-urlencoded", "multipart/form-data", ): raise ValueError("Form enctype must be " "'application/x-www-form-urlencoded' or " "'multipart/form-data', not %r" % enctype) self.enctype = enctype # The first major component of a form: its widgets. We want # both easy access and order, so we have a dictionary and a list # of the same objects. The dictionary is keyed on widget name. # These are populated by the 'add_*_widget()' methods. self.widgets = {} self.widget_order = [] self.submit_buttons = [] self.cancel_url = None # The second major component: text. It's up to the 'render()' # method to figure out how to lay these out; the standard # 'render()' does so in a fairly sensible way that should work # for most of our forms. These are also populated by the # 'add_*_widget()' methods. self.error = {} self.hint = {} self.title = {} self.required = {} config = get_publisher().config if self.method == "post" and use_tokens and config.form_tokens: # unique token for each form, this prevents many cross-site # attacks and prevents a form from being submitted twice self.add_widget(FormTokenWidget, self.TOKEN_NAME) self.use_form_tokens = 1 else: self.use_form_tokens = 0
def set_session_cookie(session_id, **attrs): """Create a cookie in the HTTP response for 'session_id'. """ config = get_publisher().config name = config.session_cookie_name if config.session_cookie_path: path = config.session_cookie_path else: path = get_request().get_environ('SCRIPT_NAME') if not path.endswith('/'): path += '/' domain = config.session_cookie_domain attrs = attrs.copy() if config.session_cookie_secure: attrs['secure'] = 1 if config.session_cookie_httponly: attrs['httponly'] = 1 get_response().set_cookie(name, session_id, domain=domain, path=path, **attrs) return name
def __init__(self, method="post", enctype=None, use_tokens=1): if method not in ("post", "get"): raise ValueError("Form method must be 'post' or 'get', " "not %r" % method) self.method = method if enctype is not None and enctype not in ( "application/x-www-form-urlencoded", "multipart/form-data"): raise ValueError, ("Form enctype must be " "'application/x-www-form-urlencoded' or " "'multipart/form-data', not %r" % enctype) self.enctype = enctype # The first major component of a form: its widgets. We want # both easy access and order, so we have a dictionary and a list # of the same objects. The dictionary is keyed on widget name. # These are populated by the 'add_*_widget()' methods. self.widgets = {} self.widget_order = [] self.submit_buttons = [] self.cancel_url = None # The second major component: text. It's up to the 'render()' # method to figure out how to lay these out; the standard # 'render()' does so in a fairly sensible way that should work # for most of our forms. These are also populated by the # 'add_*_widget()' methods. self.error = {} self.hint = {} self.title = {} self.required = {} config = get_publisher().config if self.method == "post" and use_tokens and config.form_tokens: # unique token for each form, this prevents many cross-site # attacks and prevents a form from being submitted twice self.add_widget(FormTokenWidget, self.TOKEN_NAME) self.use_form_tokens = 1 else: self.use_form_tokens = 0
def get_session(self, request): config = get_publisher().config session_id = self._get_session_id(request, config) session = None if session_id is not None: session = self.get(session_id) if session is not None and ( config.check_session_addr and session.get_remote_address() != request.get_environ("REMOTE_ADDR") ): logger.debug("Remote IP address does not match the " "IP address that created the session(%s)", session_id) session = None if session is None: session = self._create_session(request) session._set_access_time(self.ACCESS_TIME_RESOLUTION) return session
from quixote import get_publisher print(get_publisher().tenant.hostname)
from canary.ui.pages import not_found from canary.ui.about import about_ui this_module = sys.modules[__name__] contact_us = about_ui.contact_us study_methodologies = about_ui.study_methodologies linkage = about_ui.linkage tour = about_ui.tour disclaimer = about_ui.disclaimer questionnaire = about_ui.questionnaire config = get_publisher().config html_files = load_static_exports(config.static_html_dir) for file, path in html_files: _q_exports.append(file) setattr(this_module, file, MyStaticFile(path, mime_type='text/html', cache_time=30)) def _q_lookup (request, name=''): if name == 'ecohealth-2005-animals.pdf': return StaticFile(config.static_html_dir + '/ecohealth-2005-animals.pdf', mime_type='application/pdf') elif name == 'ecohealth-2004-outfoxing.pdf': return StaticFile(config.static_html_dir + '/ecohealth-2004-outfoxing.pdf', mime_type='application/pdf') else:
from quixote import get_publisher user = get_publisher().user_class() user.form_data = {} user.email = 'TEST' user.form_data['_first_name'] = 'TEST' user.form_data['_last_name'] = 'TEST' user.name_identifiers = [] user.store()
def __init__(self, username): bookmarksdb = get_publisher().context.bookmarksdb self.bookmarks = bookmarksdb[username]
from quixote import get_publisher import sys pub = get_publisher() permissions = { 'users':[], 'roles':[], 'settings':[], 'bounces':[], 'forms':[], 'workflows':[], 'categories':[] } with open("/tmp/tmp_uuid_agent_fabriques.txt", 'r') as file_aa: uuid_aa = file_aa.read() permissions['forms'].append(uuid_aa) permissions['categories'].append(uuid_aa) if len(sys.argv) > 1 and sys.argv[1] == 'full': permissions['workflows'].append(uuid_aa) file_aa.close() with open("/tmp/tmp_uuid_debug.txt", 'r') as file_debug: uuid_debug = file_debug.read() permissions['forms'].append(uuid_debug) permissions['categories'].append(uuid_debug) permissions['workflows'].append(uuid_debug) permissions['settings'].append(uuid_debug) permissions['bounces'].append(uuid_debug) pub.cfg['admin-permissions'] = permissions pub.write_cfg()
def sendmail(subject, msg_body, to_addrs, from_addr=None, cc_addrs=None, extra_headers=None, smtp_sender=None, smtp_recipients=None, mail_server=None, mail_debug_addr=None, username=None, password=None, mail_port=None, use_ssl=False, use_tls=False, config=None): """ Send an email message to a list of recipients via a local SMTP server. In normal use, you supply a list of primary recipient e-mail addresses in 'to_addrs', an optional list of secondary recipient addresses in 'cc_addrs', and a sender address in 'from_addr'. sendmail() then constructs a message using those addresses, 'subject', and 'msg_body', and mails the message to every recipient address. (Specifically, it connects to the mail server named in the MAIL_SERVER config variable -- default "localhost" -- and instructs the server to send the message to every recipient address in 'to_addrs' and 'cc_addrs'.) 'from_addr' is optional because web applications often have a common e-mail sender address, such as "*****@*****.**". Just set the Quixote config variable MAIL_FROM, and it will be used as the default sender (both header and envelope) for all e-mail sent by sendmail(). E-mail addresses can be specified a number of ways. The most efficient is to supply instances of RFC822Mailbox, which bundles a bare e-mail address (aka "addr_spec" from the RFC 822 grammar) and real name together in a readily-formattable object. You can also supply an (addr_spec, real_name) tuple, or an addr_spec on its own. The latter two are converted into RFC822Mailbox objects for formatting, which is why it may be more efficient to construct RFC822Mailbox objects yourself. Thus, the following are all equivalent in terms of who gets the message: sendmail(to_addrs=["*****@*****.**"], ...) sendmail(to_addrs=[("*****@*****.**", "Joe User")], ...) sendmail(to_addrs=[RFC822Mailbox("*****@*****.**", "Joe User")], ...) ...although the "To" header will be slightly different. In the first case, it will be To: [email protected] while in the other two, it will be: To: Joe User <*****@*****.**> which is a little more user-friendly. In more advanced usage, you might wish to specify the SMTP sender and recipient addresses separately. For example, if you want your application to send mail to users that looks like it comes from a real human being, but you don't want that human being to get the bounce messages from the mailing, you might do this: sendmail(to_addrs=user_list, ..., from_addr=("*****@*****.**", "A Real User"), smtp_sender="*****@*****.**") End users will see mail from "A Real User <*****@*****.**>" in their inbox, but bounces will go to [email protected]. One use of different header and envelope recipients is for testing/debugging. If you want to test that your application is sending the right mail to [email protected] without filling bigboss' inbox with dross, you might do this: sendmail(to_addrs=["*****@*****.**"], ..., smtp_recipients=["*****@*****.**"]) This is so useful that it's a Quixote configuration option: just set MAIL_DEBUG_ADDR to (eg.) "*****@*****.**", and every message that sendmail() would send out is diverted to the debug address. Generally raises an exception on any SMTP errors; see smtplib (in the standard library documentation) for details. """ if not mail_server and config is None: from quixote import get_publisher config = get_publisher().config from_addr = from_addr or config.mail_from mail_server = mail_server or config.mail_server if config is not None: mail_debug_addr = mail_debug_addr or config.mail_debug_addr username = username or config.mail_username password = password or config.mail_password mail_port = mail_port or config.mail_port use_ssl = use_ssl or config.mail_use_ssl use_tls = use_tls or config.mail_use_tls if not isinstance(to_addrs, list): raise TypeError("'to_addrs' must be a list") if not (cc_addrs is None or isinstance(cc_addrs, list)): raise TypeError("'cc_addrs' must be a list or None") # Make sure we have a "From" address if from_addr is None: raise RuntimeError( "no from_addr supplied, and MAIL_FROM not set in config file") # Ensure all of our addresses are really RFC822Mailbox objects. from_addr = _ensure_mailbox(from_addr) to_addrs = list(map(_ensure_mailbox, to_addrs)) if cc_addrs: cc_addrs = list(map(_ensure_mailbox, cc_addrs)) # Start building the message headers. headers = ["From: %s" % from_addr.format(), "Subject: %s" % _encode_header(subject)] _add_recip_headers(headers, "To", to_addrs) if cc_addrs: _add_recip_headers(headers, "Cc", cc_addrs) if extra_headers: headers.extend(extra_headers) # add a Content-Type header if there isn't already one for hdr in headers: name, _, value = hdr.partition(':') if name.lower() == 'content-type': break else: headers.append('Content-Type: text/plain; charset=%s' % EMAIL_ENCODING) if mail_debug_addr: debug1 = ("[debug mode, message actually sent to %s]\n" % mail_debug_addr) if smtp_recipients: debug2 = ("[original SMTP recipients: %s]\n" % ", ".join(smtp_recipients)) else: debug2 = "" sep = ("-"*72) + "\n" msg_body = debug1 + debug2 + sep + msg_body smtp_recipients = [mail_debug_addr] if smtp_sender is None: smtp_sender = from_addr.addr_spec else: smtp_sender = _ensure_mailbox(smtp_sender).addr_spec if smtp_recipients is None: smtp_recipients = [addr.addr_spec for addr in to_addrs] if cc_addrs: smtp_recipients.extend([addr.addr_spec for addr in cc_addrs]) else: smtp_recipients = [_ensure_mailbox(recip).addr_spec for recip in smtp_recipients] message = "\n".join(headers) + "\n\n" + msg_body # smtplib requires bytes message = message.encode(EMAIL_ENCODING) if not mail_port: if use_ssl: mail_port = 465 elif use_tls: mail_port = 587 else: mail_port = 25 if ssl and (use_ssl or use_tls): context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) if config and config.mail_allow_sslv3: # need to allow SSLv3 for old servers, even though it is broken context.options &= ~ssl.OP_NO_SSLv3 else: context = None if use_ssl: smtp = SMTP_SSL(mail_server, port=mail_port, context=context) else: smtp = SMTP(mail_server, port=mail_port) smtp.ehlo() if use_tls: smtp.starttls(context=context) smtp.ehlo() if username: smtp.login(username, password) smtp.sendmail(smtp_sender, smtp_recipients, message) smtp.quit()
def sendmail(subject, msg_body, to_addrs, from_addr=None, cc_addrs=None, extra_headers=None, smtp_sender=None, smtp_recipients=None, config=None): """sendmail(subject : string, msg_body : string, to_addrs : [email_address], from_addr : email_address = config.MAIL_SENDER, cc_addrs : [email_address] = None, extra_headers : [string] = None, smtp_sender : email_address = (derived from from_addr) smtp_recipients : [email_address] = (derived from to_addrs), config : quixote.config.Config = (current publisher's config)): Send an email message to a list of recipients via a local SMTP server. In normal use, you supply a list of primary recipient e-mail addresses in 'to_addrs', an optional list of secondary recipient addresses in 'cc_addrs', and a sender address in 'from_addr'. sendmail() then constructs a message using those addresses, 'subject', and 'msg_body', and mails the message to every recipient address. (Specifically, it connects to the mail server named in the MAIL_SERVER config variable -- default "localhost" -- and instructs the server to send the message to every recipient address in 'to_addrs' and 'cc_addrs'.) 'from_addr' is optional because web applications often have a common e-mail sender address, such as "*****@*****.**". Just set the Quixote config variable MAIL_FROM, and it will be used as the default sender (both header and envelope) for all e-mail sent by sendmail(). E-mail addresses can be specified a number of ways. The most efficient is to supply instances of RFC822Mailbox, which bundles a bare e-mail address (aka "addr_spec" from the RFC 822 grammar) and real name together in a readily-formattable object. You can also supply an (addr_spec, real_name) tuple, or an addr_spec on its own. The latter two are converted into RFC822Mailbox objects for formatting, which is why it may be more efficient to construct RFC822Mailbox objects yourself. Thus, the following are all equivalent in terms of who gets the message: sendmail(to_addrs=["*****@*****.**"], ...) sendmail(to_addrs=[("*****@*****.**", "Joe User")], ...) sendmail(to_addrs=[RFC822Mailbox("*****@*****.**", "Joe User")], ...) ...although the "To" header will be slightly different. In the first case, it will be To: [email protected] while in the other two, it will be: To: Joe User <*****@*****.**> which is a little more user-friendly. In more advanced usage, you might wish to specify the SMTP sender and recipient addresses separately. For example, if you want your application to send mail to users that looks like it comes from a real human being, but you don't want that human being to get the bounce messages from the mailing, you might do this: sendmail(to_addrs=user_list, ..., from_addr=("*****@*****.**", "A Real User"), smtp_sender="*****@*****.**") End users will see mail from "A Real User <*****@*****.**>" in their inbox, but bounces will go to [email protected]. One use of different header and envelope recipients is for testing/debugging. If you want to test that your application is sending the right mail to [email protected] without filling bigboss' inbox with dross, you might do this: sendmail(to_addrs=["*****@*****.**"], ..., smtp_recipients=["*****@*****.**"]) This is so useful that it's a Quixote configuration option: just set MAIL_DEBUG_ADDR to (eg.) "*****@*****.**", and every message that sendmail() would send out is diverted to the debug address. Generally raises an exception on any SMTP errors; see smtplib (in the standard library documentation) for details. """ if config is None: from quixote import get_publisher config = get_publisher().config if not isinstance(to_addrs, ListType): raise TypeError("'to_addrs' must be a list") if not (cc_addrs is None or isinstance(cc_addrs, ListType)): raise TypeError("'cc_addrs' must be a list or None") # Make sure we have a "From" address if from_addr is None: from_addr = config.mail_from if from_addr is None: raise RuntimeError( "no from_addr supplied, and MAIL_FROM not set in config file") # Ensure all of our addresses are really RFC822Mailbox objects. from_addr = _ensure_mailbox(from_addr) to_addrs = map(_ensure_mailbox, to_addrs) if cc_addrs: cc_addrs = map(_ensure_mailbox, cc_addrs) # Start building the message headers. headers = ["From: %s" % from_addr.format(), "Subject: %s" % subject] _add_recip_headers(headers, "To", to_addrs) if cc_addrs: _add_recip_headers(headers, "Cc", cc_addrs) if extra_headers: headers.extend(extra_headers) if config.mail_debug_addr: debug1 = ("[debug mode, message actually sent to %s]\n" % config.mail_debug_addr) if smtp_recipients: debug2 = ("[original SMTP recipients: %s]\n" % ", ".join(smtp_recipients)) else: debug2 = "" sep = ("-" * 72) + "\n" msg_body = debug1 + debug2 + sep + msg_body smtp_recipients = [config.mail_debug_addr] if smtp_sender is None: smtp_sender = from_addr.addr_spec else: smtp_sender = _ensure_mailbox(smtp_sender).addr_spec if smtp_recipients is None: smtp_recipients = [addr.addr_spec for addr in to_addrs] if cc_addrs: smtp_recipients.extend([addr.addr_spec for addr in cc_addrs]) else: smtp_recipients = [ _ensure_mailbox(recip).addr_spec for recip in smtp_recipients ] message = "\n".join(headers) + "\n\n" + msg_body # Sanity checks assert type(smtp_sender) is StringType, \ "smtp_sender not a string: %r" % (smtp_sender,) assert (type(smtp_recipients) is ListType and map(type, smtp_recipients) == [StringType]*len(smtp_recipients)), \ "smtp_recipients not a list of strings: %r" % (smtp_recipients,) smtp = SMTP(config.mail_server) smtp.sendmail(smtp_sender, smtp_recipients, message) smtp.quit()
def _q_resolve(self, name): if name == "static": return StaticDirectory(get_publisher().context.app_options.get( "server", "static_content"))
def sendmail(subject, msg_body, to_addrs, from_addr=None, cc_addrs=None, extra_headers=None, smtp_sender=None, smtp_recipients=None, config=None): """sendmail(subject : string, msg_body : string, to_addrs : [email_address], from_addr : email_address = config.MAIL_SENDER, cc_addrs : [email_address] = None, extra_headers : [string] = None, smtp_sender : email_address = (derived from from_addr) smtp_recipients : [email_address] = (derived from to_addrs), config : quixote.config.Config = (current publisher's config)): Send an email message to a list of recipients via a local SMTP server. In normal use, you supply a list of primary recipient e-mail addresses in 'to_addrs', an optional list of secondary recipient addresses in 'cc_addrs', and a sender address in 'from_addr'. sendmail() then constructs a message using those addresses, 'subject', and 'msg_body', and mails the message to every recipient address. (Specifically, it connects to the mail server named in the MAIL_SERVER config variable -- default "localhost" -- and instructs the server to send the message to every recipient address in 'to_addrs' and 'cc_addrs'.) 'from_addr' is optional because web applications often have a common e-mail sender address, such as "*****@*****.**". Just set the Quixote config variable MAIL_FROM, and it will be used as the default sender (both header and envelope) for all e-mail sent by sendmail(). E-mail addresses can be specified a number of ways. The most efficient is to supply instances of RFC822Mailbox, which bundles a bare e-mail address (aka "addr_spec" from the RFC 822 grammar) and real name together in a readily-formattable object. You can also supply an (addr_spec, real_name) tuple, or an addr_spec on its own. The latter two are converted into RFC822Mailbox objects for formatting, which is why it may be more efficient to construct RFC822Mailbox objects yourself. Thus, the following are all equivalent in terms of who gets the message: sendmail(to_addrs=["*****@*****.**"], ...) sendmail(to_addrs=[("*****@*****.**", "Joe User")], ...) sendmail(to_addrs=[RFC822Mailbox("*****@*****.**", "Joe User")], ...) ...although the "To" header will be slightly different. In the first case, it will be To: [email protected] while in the other two, it will be: To: Joe User <*****@*****.**> which is a little more user-friendly. In more advanced usage, you might wish to specify the SMTP sender and recipient addresses separately. For example, if you want your application to send mail to users that looks like it comes from a real human being, but you don't want that human being to get the bounce messages from the mailing, you might do this: sendmail(to_addrs=user_list, ..., from_addr=("*****@*****.**", "A Real User"), smtp_sender="*****@*****.**") End users will see mail from "A Real User <*****@*****.**>" in their inbox, but bounces will go to [email protected]. One use of different header and envelope recipients is for testing/debugging. If you want to test that your application is sending the right mail to [email protected] without filling bigboss' inbox with dross, you might do this: sendmail(to_addrs=["*****@*****.**"], ..., smtp_recipients=["*****@*****.**"]) This is so useful that it's a Quixote configuration option: just set MAIL_DEBUG_ADDR to (eg.) "*****@*****.**", and every message that sendmail() would send out is diverted to the debug address. Generally raises an exception on any SMTP errors; see smtplib (in the standard library documentation) for details. """ if config is None: from quixote import get_publisher config = get_publisher().config if not isinstance(to_addrs, ListType): raise TypeError("'to_addrs' must be a list") if not (cc_addrs is None or isinstance(cc_addrs, ListType)): raise TypeError("'cc_addrs' must be a list or None") # Make sure we have a "From" address if from_addr is None: from_addr = config.mail_from if from_addr is None: raise RuntimeError( "no from_addr supplied, and MAIL_FROM not set in config file") # Ensure all of our addresses are really RFC822Mailbox objects. from_addr = _ensure_mailbox(from_addr) to_addrs = map(_ensure_mailbox, to_addrs) if cc_addrs: cc_addrs = map(_ensure_mailbox, cc_addrs) # Start building the message headers. headers = ["From: %s" % from_addr.format(), "Subject: %s" % subject] _add_recip_headers(headers, "To", to_addrs) if cc_addrs: _add_recip_headers(headers, "Cc", cc_addrs) if extra_headers: headers.extend(extra_headers) if config.mail_debug_addr: debug1 = ("[debug mode, message actually sent to %s]\n" % config.mail_debug_addr) if smtp_recipients: debug2 = ("[original SMTP recipients: %s]\n" % ", ".join(smtp_recipients)) else: debug2 = "" sep = ("-"*72) + "\n" msg_body = debug1 + debug2 + sep + msg_body smtp_recipients = [config.mail_debug_addr] if smtp_sender is None: smtp_sender = from_addr.addr_spec else: smtp_sender = _ensure_mailbox(smtp_sender).addr_spec if smtp_recipients is None: smtp_recipients = [addr.addr_spec for addr in to_addrs] if cc_addrs: smtp_recipients.extend([addr.addr_spec for addr in cc_addrs]) else: smtp_recipients = [_ensure_mailbox(recip).addr_spec for recip in smtp_recipients] message = "\n".join(headers) + "\n\n" + msg_body # Sanity checks assert type(smtp_sender) is StringType, \ "smtp_sender not a string: %r" % (smtp_sender,) assert (type(smtp_recipients) is ListType and map(type, smtp_recipients) == [StringType]*len(smtp_recipients)), \ "smtp_recipients not a list of strings: %r" % (smtp_recipients,) smtp = SMTP(config.mail_server) smtp.sendmail(smtp_sender, smtp_recipients, message) smtp.quit()
# iMio 2021 # dmuyshond # It's been needed to be certain trace errors are send to [email protected] # Since it was not automatic and we did not receive important error traces by mail # It's now used in our build-e-guichet.sh for newcoming cities # More info : https://dev.entrouvert.org/issues/44210 # https://support.imio.be/browse/TELE-653 from quixote import get_publisher pub = get_publisher() pub.reload_cfg() debug = pub.cfg.get('debug') if not debug: debug = {'error_email': '*****@*****.**'} print(" --- admin TS mail adress has been set-up (mail for error traces).") else: if 'admints' not in debug['error_email']: print(" --- Attention, l'adresse admin TS n'est pas set.") print(" 'error_email' contient ceci : ", debug['error_email']) pub.cfg['debug'] = debug pub.write_cfg()