398e258ed1330421291f943298e7f801f7b05bf8 hiram Thu Apr 23 15:05:02 2026 -0700 and send notification email to the requesting user refs #31811 diff --git src/hg/utils/otto/userRequests/ottoRequest.py src/hg/utils/otto/userRequests/ottoRequest.py index e148a9ced65..dca2df5f3ef 100755 --- src/hg/utils/otto/userRequests/ottoRequest.py +++ src/hg/utils/otto/userRequests/ottoRequest.py @@ -68,35 +68,45 @@ 'requestTime': fields[6], }) return rows def hgsqlUpdate(db, sql): """Run a SQL update/insert statement via hgsql.""" cmd = ['hgsql', db, '-N', '-B', '-e', sql] result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode != 0: print(f"hgsql update error: {result.stderr.strip()}", file=sys.stderr) return False return True -def sendMail(toAddr, subject, body): - """Send email via /usr/sbin/sendmail.""" - message = f"To: {toAddr}\nSubject: {subject}\n\n{body}\n" - result = subprocess.run(['/usr/sbin/sendmail', '-t'], - input=message, capture_output=True, text=True) +def sendMail(toAddr, subject, body, fromAddr=None): + """Send email via /usr/sbin/sendmail. + If fromAddr is provided it is used as the envelope sender (-f) + and the From: header so that bounces return to that address.""" + headers = f"To: {toAddr}\nSubject: {subject}" + if fromAddr: + headers = (f"From: {fromAddr}\n" + f"Reply-To: {fromAddr}\n" + f"Return-Path: {fromAddr}\n" + f"{headers}") + message = f"{headers}\n\n{body}\n" + cmd = ['/usr/sbin/sendmail', '-t'] + if fromAddr: + cmd += ['-f', fromAddr] + result = subprocess.run(cmd, input=message, capture_output=True, text=True) if result.returncode != 0: print(f"Warning: sendmail failed: {result.stderr.strip()}", file=sys.stderr) return False return True def main(): parser = argparse.ArgumentParser( description='Process pending ottoRequest entries.') parser.add_argument('-c', '--conf', default='/usr/local/apache/cgi-bin/hg.conf', help='Path to hg.conf [default: %(default)s]') args = parser.parse_args() @@ -123,27 +133,52 @@ for req in pending: subject = f"ottoRequest #{req['id']}: {req['requestType']} pending" body = ( f"##################################################\n" f"Pending {req['requestType']} request #{req['id']}\n" f"\n" f" From: {req['fromDb']}\n" f" To: {req['toDb']}\n" f" Email: {req['email']}\n" f" Comment: {req['comment']}\n" f" Time: {req['requestTime']}\n" f"##################################################\n" f"testing ottoRequest watch cron job\n" f"##################################################\n" ) - if sendMail(notifyEmail, subject, body): + if sendMail(notifyEmail, subject, body, fromAddr=notifyEmail): # print(f"Notified {notifyEmail} about request #{req['id']}") hgsqlUpdate(dbName, f"UPDATE {table} SET doneStatus = 1" f" WHERE id = {req['id']}") else: print(f"Failed to notify about request #{req['id']}", file=sys.stderr) + # send acknowledgment to the requesting user + userEmail = req.get('email', '') + if userEmail: + userSubject = (f"UCSC Genome Browser: your {req['requestType']}" + f" request has been received") + userBody = ( + f"Your request for chain/liftOver files has been received\n" + f"and is being processed.\n" + f"\n" + f"Request details:\n" + f" Type: {req['requestType']}\n" + f" From: {req['fromDb']}\n" + f" To: {req['toDb']}\n" + f" Submitted: {req['requestTime']}\n" + f"\n" + f"You will receive another email when your files are ready.\n" + f"\n" + f"- UCSC Genome Browser\n" + ) + if not sendMail(userEmail, userSubject, userBody, + fromAddr=notifyEmail): + print(f"Warning: failed to send acknowledgment to" + f" {userEmail} for request #{req['id']}", + file=sys.stderr) + if __name__ == '__main__': main()