mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge pull request #15557 from jdavcs/dev_emailfrom
Handle "email_from" config option consistently, as per schema description
This commit is contained in:
@@ -30,6 +30,7 @@ from typing import (
|
||||
TypeVar,
|
||||
Union,
|
||||
)
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import yaml
|
||||
|
||||
@@ -135,6 +136,7 @@ LOGGING_CONFIG_DEFAULT: Dict[str, Any] = {
|
||||
"""Default value for logging configuration, passed to :func:`logging.config.dictConfig`"""
|
||||
|
||||
VERSION_JSON_FILE = "version.json"
|
||||
DEFAULT_EMAIL_FROM_LOCAL_PART = "galaxy-no-reply"
|
||||
|
||||
|
||||
def configure_logging(config, facts=None):
|
||||
@@ -612,16 +614,6 @@ class CommonConfigurationMixin:
|
||||
|
||||
|
||||
class GalaxyAppConfiguration(BaseAppConfiguration, CommonConfigurationMixin):
|
||||
deprecated_options = (
|
||||
"database_file",
|
||||
"track_jobs_in_database",
|
||||
"blacklist_file",
|
||||
"whitelist_file",
|
||||
"sanitize_whitelist_file",
|
||||
"user_library_import_symlink_whitelist",
|
||||
"fetch_url_whitelist",
|
||||
"containers_resolvers_config_file",
|
||||
)
|
||||
renamed_options = {
|
||||
"blacklist_file": "email_domain_blocklist_file",
|
||||
"whitelist_file": "email_domain_allowlist_file",
|
||||
@@ -629,7 +621,14 @@ class GalaxyAppConfiguration(BaseAppConfiguration, CommonConfigurationMixin):
|
||||
"user_library_import_symlink_whitelist": "user_library_import_symlink_allowlist",
|
||||
"fetch_url_whitelist": "fetch_url_allowlist",
|
||||
"containers_resolvers_config_file": "container_resolvers_config_file",
|
||||
"activation_email": "email_from",
|
||||
}
|
||||
|
||||
deprecated_options = list(renamed_options.keys()) + [
|
||||
"database_file",
|
||||
"track_jobs_in_database",
|
||||
]
|
||||
|
||||
default_config_file_name = "galaxy.yml"
|
||||
deprecated_dirs = {"config_dir": "config", "data_dir": "database"}
|
||||
|
||||
@@ -895,8 +894,6 @@ class GalaxyAppConfiguration(BaseAppConfiguration, CommonConfigurationMixin):
|
||||
self.nodejs_path = kwargs.get("nodejs_path")
|
||||
self.container_image_cache_path = self._in_data_dir(kwargs.get("container_image_cache_path", "container_cache"))
|
||||
self.output_size_limit = int(kwargs.get("output_size_limit", 0))
|
||||
# activation_email was used until release_15.03
|
||||
self.email_from = self.email_from or kwargs.get("activation_email")
|
||||
|
||||
self.email_domain_blocklist_content = (
|
||||
self._load_list_from_file(self._in_config_dir(self.email_domain_blocklist_file))
|
||||
@@ -1046,7 +1043,7 @@ class GalaxyAppConfiguration(BaseAppConfiguration, CommonConfigurationMixin):
|
||||
if section.startswith("server:"):
|
||||
self.server_names.append(section.replace("server:", "", 1))
|
||||
|
||||
self._set_galaxy_infrastructure_url(kwargs)
|
||||
self._set_host_related_options(kwargs)
|
||||
|
||||
# Asynchronous execution process pools - limited functionality for now, attach_to_pools is designed to allow
|
||||
# webless Galaxy server processes to attach to arbitrary message queues (e.g. as job handlers) so they do not
|
||||
@@ -1209,6 +1206,12 @@ class GalaxyAppConfiguration(BaseAppConfiguration, CommonConfigurationMixin):
|
||||
with open(filepath) as f:
|
||||
return [line.strip() for line in f]
|
||||
|
||||
def _set_host_related_options(self, kwargs):
|
||||
# The following 3 method calls must be made in sequence
|
||||
self._set_galaxy_infrastructure_url(kwargs)
|
||||
self._set_hostname()
|
||||
self._set_email_from()
|
||||
|
||||
def _set_galaxy_infrastructure_url(self, kwargs):
|
||||
# indicate if this was not set explicitly, so dependending on the context a better default
|
||||
# can be used (request url in a web thread, Docker parent in IE stuff, etc.)
|
||||
@@ -1227,6 +1230,16 @@ class GalaxyAppConfiguration(BaseAppConfiguration, CommonConfigurationMixin):
|
||||
if "UWSGI_PORT" in self.galaxy_infrastructure_url:
|
||||
raise Exception("UWSGI_PORT is not supported anymore")
|
||||
|
||||
def _set_hostname(self):
|
||||
if self.galaxy_infrastructure_url_set:
|
||||
self.hostname = urlparse(self.galaxy_infrastructure_url).hostname
|
||||
else:
|
||||
self.hostname = socket.getfqdn()
|
||||
|
||||
def _set_email_from(self):
|
||||
if not self.email_from:
|
||||
self.email_from = f"{DEFAULT_EMAIL_FROM_LOCAL_PART}@{self.hostname}"
|
||||
|
||||
def reload_sanitize_allowlist(self, explicit=True):
|
||||
self.sanitize_allowlist = []
|
||||
if not os.path.exists(self.sanitize_allowlist_file):
|
||||
|
||||
@@ -3,7 +3,6 @@ Actions to be run at job completion (or output hda creation, as in the case of
|
||||
immediate_actions listed below.
|
||||
"""
|
||||
import datetime
|
||||
import socket
|
||||
|
||||
from markupsafe import escape
|
||||
|
||||
@@ -53,7 +52,6 @@ class EmailAction(DefaultJobAction):
|
||||
@classmethod
|
||||
def execute(cls, app, sa_session, action, job, replacement_dict, final_job_state=None):
|
||||
try:
|
||||
frm = app.config.email_from
|
||||
history_id_encoded = app.security.encode_id(job.history_id)
|
||||
link_invocation = None
|
||||
if job.workflow_invocation_step:
|
||||
@@ -62,19 +60,13 @@ class EmailAction(DefaultJobAction):
|
||||
f"{app.config.galaxy_infrastructure_url}/workflows/invocations/report?id={invocation_id_encoded}"
|
||||
)
|
||||
link = f"{app.config.galaxy_infrastructure_url}/histories/view?id={history_id_encoded}"
|
||||
if frm is None:
|
||||
if action.action_arguments and "host" in action.action_arguments:
|
||||
host = action.action_arguments["host"]
|
||||
else:
|
||||
host = socket.getfqdn()
|
||||
frm = f"galaxy-no-reply@{host}"
|
||||
to = job.get_user_email()
|
||||
subject = f"Galaxy job completion notification from history '{job.history.name}'"
|
||||
outdata = ",\n".join(ds.dataset.display_name() for ds in job.output_datasets)
|
||||
body = f"Your Galaxy job generating dataset(s):\n\n{outdata}\n\nis complete as of {datetime.datetime.now().strftime('%I:%M')}. Click the link below to access your data: \n{link}"
|
||||
if link_invocation:
|
||||
body += f"\n\nWorkflow Invocation Report:\n{link_invocation}"
|
||||
send_mail(frm, to, subject, body, app.config)
|
||||
send_mail(app.config.email_from, to, subject, body, app.config)
|
||||
except Exception as e:
|
||||
log.error("EmailAction PJA Failed, exception: %s", unicodify(e))
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import hashlib
|
||||
import logging
|
||||
import random
|
||||
import re
|
||||
import socket
|
||||
import time
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
@@ -484,7 +483,6 @@ class UserManager(base.ModelManager, deletable.PurgableManagerMixin):
|
||||
activation_link = url_for(
|
||||
controller="user", action="activate", activation_token=activation_token, email=escape(email), qualified=True
|
||||
)
|
||||
host = self.__get_host(trans)
|
||||
template_context = {
|
||||
"name": escape(username),
|
||||
"user_email": escape(email),
|
||||
@@ -500,10 +498,9 @@ class UserManager(base.ModelManager, deletable.PurgableManagerMixin):
|
||||
body = templates.render(TXT_ACTIVATION_EMAIL_TEMPLATE_RELPATH, template_context, self.app.config.templates_dir)
|
||||
html = templates.render(HTML_ACTIVATION_EMAIL_TEMPLATE_RELPATH, template_context, self.app.config.templates_dir)
|
||||
to = email
|
||||
frm = self.app.config.email_from or f"galaxy-no-reply@{host}"
|
||||
subject = "Galaxy Account Activation"
|
||||
try:
|
||||
util.send_mail(frm, to, subject, body, self.app.config, html=html)
|
||||
util.send_mail(self.app.config.email_from, to, subject, body, self.app.config, html=html)
|
||||
return True
|
||||
except Exception:
|
||||
log.debug(body)
|
||||
@@ -536,18 +533,16 @@ class UserManager(base.ModelManager, deletable.PurgableManagerMixin):
|
||||
else:
|
||||
reset_user, prt = self.get_reset_token(trans, email)
|
||||
if prt:
|
||||
host = self.__get_host(trans)
|
||||
reset_url = url_for(controller="login", action="start", token=prt.token)
|
||||
body = PASSWORD_RESET_TEMPLATE % (
|
||||
host,
|
||||
trans.app.config.hostname,
|
||||
prt.expiration_time.strftime(trans.app.config.pretty_datetime_format),
|
||||
trans.request.host,
|
||||
reset_url,
|
||||
)
|
||||
frm = trans.app.config.email_from or f"galaxy-no-reply@{host}"
|
||||
subject = "Galaxy Password Reset"
|
||||
try:
|
||||
util.send_mail(frm, email, subject, body, self.app.config)
|
||||
util.send_mail(trans.app.config.email_from, email, subject, body, self.app.config)
|
||||
trans.sa_session.add(reset_user)
|
||||
trans.sa_session.flush()
|
||||
trans.log_event(f"User reset password: {email}")
|
||||
@@ -574,12 +569,6 @@ class UserManager(base.ModelManager, deletable.PurgableManagerMixin):
|
||||
return reset_user, prt
|
||||
return None, None
|
||||
|
||||
def __get_host(self, trans):
|
||||
host = trans.request.host.split(":")[0]
|
||||
if host in ["localhost", "127.0.0.1", "0.0.0.0"]:
|
||||
host = socket.getfqdn()
|
||||
return host
|
||||
|
||||
def send_subscription_email(self, email):
|
||||
if self.app.config.smtp_server is None:
|
||||
return "Subscribing to the mailing list has failed because mail is not configured for this Galaxy instance. Please contact your local Galaxy administrator."
|
||||
|
||||
@@ -243,7 +243,6 @@ class EmailErrorReporter(ErrorReporter):
|
||||
to = self.app.config.error_email_to
|
||||
assert to, ValueError("Error reporting has been disabled for this Galaxy instance")
|
||||
|
||||
frm = self.app.config.email_from
|
||||
error_msg = validate_email_str(email)
|
||||
if not error_msg and self._can_access_dataset(user):
|
||||
to += f", {email.strip()}"
|
||||
@@ -255,4 +254,6 @@ class EmailErrorReporter(ErrorReporter):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return util.send_mail(frm, to, subject, self.report, self.app.config, html=self.html_report)
|
||||
return util.send_mail(
|
||||
self.app.config.email_from, to, subject, self.report, self.app.config, html=self.html_report
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ import os
|
||||
import pytest
|
||||
|
||||
from galaxy import config
|
||||
from galaxy.config import DEFAULT_EMAIL_FROM_LOCAL_PART
|
||||
from galaxy.util.properties import running_from_source
|
||||
|
||||
|
||||
@@ -42,3 +43,10 @@ def test_base_config_if_running_not_from_source(monkeypatch):
|
||||
assert appconfig.config_dir == os.getcwd()
|
||||
assert appconfig.data_dir == os.path.join(appconfig.config_dir, "data")
|
||||
assert appconfig.managed_config_dir == os.path.join(appconfig.data_dir, "config")
|
||||
|
||||
|
||||
def test_assign_email_from(monkeypatch):
|
||||
appconfig = config.GalaxyAppConfiguration(
|
||||
override_tempdir=False, galaxy_infrastructure_url="http://myhost:8080/galaxy/"
|
||||
)
|
||||
assert appconfig.email_from == f"{DEFAULT_EMAIL_FROM_LOCAL_PART}@myhost"
|
||||
|
||||
Reference in New Issue
Block a user