Make from number optional, Sinch auto-assigns

Tested: Sinch sends faxes without a from number, auto-assigns a
service. Simplifies setup - no need to purchase a number.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sochen 2026-03-06 22:33:45 +00:00
parent 4dc9d9330d
commit 521e7b03e0
4 changed files with 14 additions and 16 deletions

View file

@ -5,14 +5,13 @@ SINCH_PROJECT_ID=your_project_id
SINCH_KEY_ID=your_key_id
SINCH_KEY_SECRET=your_key_secret
# Your Sinch fax-enabled phone number (E.164 format)
# Purchase one in the Sinch dashboard under Numbers
SINCH_FROM_NUMBER=+1XXXXXXXXXX
# Your Sinch fax-enabled phone number (optional, Sinch auto-assigns one)
# SINCH_FROM_NUMBER=+1XXXXXXXXXX
# Destination fax number (E.164 format)
# Use +19898989898 for free test faxes (no charge, simulates delivery)
FAX_TO_NUMBER=+1XXXXXXXXXX
# ntfy notification URL (optional, comment out to disable)
# NTFY_URL=https://nt.nevo.engineer/your-channel
# NTFY_URL=https://ntfy.sh/your-topic
# NTFY_TOKEN=Bearer tk_your_token_here

View file

@ -36,10 +36,10 @@ def send_fax(pdf_path: Path) -> dict:
f"{API}/faxes",
auth=auth(),
files={"file": (pdf_path.name, f, "application/pdf")},
data={
data={k: v for k, v in {
"to": config.FAX_TO_NUMBER,
"from": config.SINCH_FROM_NUMBER,
},
"from": config.SINCH_FROM_NUMBER or None,
}.items() if v},
timeout=60,
)
resp.raise_for_status()

View file

@ -14,7 +14,7 @@ LOG_FILE = REPORTS_DIR / "fax_log.json"
SINCH_PROJECT_ID = os.environ["SINCH_PROJECT_ID"]
SINCH_KEY_ID = os.environ["SINCH_KEY_ID"]
SINCH_KEY_SECRET = os.environ["SINCH_KEY_SECRET"]
SINCH_FROM_NUMBER = os.environ["SINCH_FROM_NUMBER"]
SINCH_FROM_NUMBER = os.environ.get("SINCH_FROM_NUMBER", "") # optional, Sinch auto-assigns
FAX_TO_NUMBER = os.environ["FAX_TO_NUMBER"]
# ntfy (optional)

15
gui.py
View file

@ -97,7 +97,7 @@ class AutoFaxApp:
self._add_field(lf_sinch, "Project ID:", self.project_id_var)
self._add_field(lf_sinch, "Key ID:", self.key_id_var)
self._add_field(lf_sinch, "Key Secret:", self.key_secret_var, show="*")
self._add_field(lf_sinch, "From Number:", self.from_var, placeholder="+1XXXXXXXXXX")
self._add_field(lf_sinch, "From (optional):", self.from_var, placeholder="+1XXXXXXXXXX")
# ── Fax Settings ──
lf_fax = tk.LabelFrame(main, text="Fax Settings", padx=10, pady=5)
@ -207,9 +207,6 @@ class AutoFaxApp:
problems.append("Key ID is required")
if not self.key_secret_var.get().strip():
problems.append("Key Secret is required")
from_num = self.from_var.get().strip()
if not from_num or from_num == "+1XXXXXXXXXX":
problems.append("From Number is required")
to_num = self.to_var.get().strip()
if not to_num or to_num == "+18019382102":
problems.append("To Number is required")
@ -273,19 +270,21 @@ class AutoFaxApp:
pdf_path = Path(self.pdf_var.get().strip())
to_number = self.to_var.get().strip()
from_number = self.from_var.get().strip()
if from_number == "+1XXXXXXXXXX":
from_number = ""
timestamp = datetime.now(timezone.utc).isoformat()
try:
self.log(f"Sending fax to {to_number}...")
form_data = {"to": to_number}
if from_number:
form_data["from"] = from_number
with open(pdf_path, "rb") as f:
resp = requests.post(
f"{self._api_url()}/faxes",
auth=self._auth(),
files={"file": (pdf_path.name, f, "application/pdf")},
data={
"to": to_number,
"from": from_number,
},
data=form_data,
timeout=60,
)
resp.raise_for_status()