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:
parent
4dc9d9330d
commit
521e7b03e0
4 changed files with 14 additions and 16 deletions
|
|
@ -5,14 +5,13 @@ SINCH_PROJECT_ID=your_project_id
|
||||||
SINCH_KEY_ID=your_key_id
|
SINCH_KEY_ID=your_key_id
|
||||||
SINCH_KEY_SECRET=your_key_secret
|
SINCH_KEY_SECRET=your_key_secret
|
||||||
|
|
||||||
# Your Sinch fax-enabled phone number (E.164 format)
|
# Your Sinch fax-enabled phone number (optional, Sinch auto-assigns one)
|
||||||
# Purchase one in the Sinch dashboard under Numbers
|
# SINCH_FROM_NUMBER=+1XXXXXXXXXX
|
||||||
SINCH_FROM_NUMBER=+1XXXXXXXXXX
|
|
||||||
|
|
||||||
# Destination fax number (E.164 format)
|
# Destination fax number (E.164 format)
|
||||||
# Use +19898989898 for free test faxes (no charge, simulates delivery)
|
# Use +19898989898 for free test faxes (no charge, simulates delivery)
|
||||||
FAX_TO_NUMBER=+1XXXXXXXXXX
|
FAX_TO_NUMBER=+1XXXXXXXXXX
|
||||||
|
|
||||||
# ntfy notification URL (optional, comment out to disable)
|
# 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
|
# NTFY_TOKEN=Bearer tk_your_token_here
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,10 @@ def send_fax(pdf_path: Path) -> dict:
|
||||||
f"{API}/faxes",
|
f"{API}/faxes",
|
||||||
auth=auth(),
|
auth=auth(),
|
||||||
files={"file": (pdf_path.name, f, "application/pdf")},
|
files={"file": (pdf_path.name, f, "application/pdf")},
|
||||||
data={
|
data={k: v for k, v in {
|
||||||
"to": config.FAX_TO_NUMBER,
|
"to": config.FAX_TO_NUMBER,
|
||||||
"from": config.SINCH_FROM_NUMBER,
|
"from": config.SINCH_FROM_NUMBER or None,
|
||||||
},
|
}.items() if v},
|
||||||
timeout=60,
|
timeout=60,
|
||||||
)
|
)
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ LOG_FILE = REPORTS_DIR / "fax_log.json"
|
||||||
SINCH_PROJECT_ID = os.environ["SINCH_PROJECT_ID"]
|
SINCH_PROJECT_ID = os.environ["SINCH_PROJECT_ID"]
|
||||||
SINCH_KEY_ID = os.environ["SINCH_KEY_ID"]
|
SINCH_KEY_ID = os.environ["SINCH_KEY_ID"]
|
||||||
SINCH_KEY_SECRET = os.environ["SINCH_KEY_SECRET"]
|
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"]
|
FAX_TO_NUMBER = os.environ["FAX_TO_NUMBER"]
|
||||||
|
|
||||||
# ntfy (optional)
|
# ntfy (optional)
|
||||||
|
|
|
||||||
15
gui.py
15
gui.py
|
|
@ -97,7 +97,7 @@ class AutoFaxApp:
|
||||||
self._add_field(lf_sinch, "Project ID:", self.project_id_var)
|
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 ID:", self.key_id_var)
|
||||||
self._add_field(lf_sinch, "Key Secret:", self.key_secret_var, show="*")
|
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 ──
|
# ── Fax Settings ──
|
||||||
lf_fax = tk.LabelFrame(main, text="Fax Settings", padx=10, pady=5)
|
lf_fax = tk.LabelFrame(main, text="Fax Settings", padx=10, pady=5)
|
||||||
|
|
@ -207,9 +207,6 @@ class AutoFaxApp:
|
||||||
problems.append("Key ID is required")
|
problems.append("Key ID is required")
|
||||||
if not self.key_secret_var.get().strip():
|
if not self.key_secret_var.get().strip():
|
||||||
problems.append("Key Secret is required")
|
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()
|
to_num = self.to_var.get().strip()
|
||||||
if not to_num or to_num == "+18019382102":
|
if not to_num or to_num == "+18019382102":
|
||||||
problems.append("To Number is required")
|
problems.append("To Number is required")
|
||||||
|
|
@ -273,19 +270,21 @@ class AutoFaxApp:
|
||||||
pdf_path = Path(self.pdf_var.get().strip())
|
pdf_path = Path(self.pdf_var.get().strip())
|
||||||
to_number = self.to_var.get().strip()
|
to_number = self.to_var.get().strip()
|
||||||
from_number = self.from_var.get().strip()
|
from_number = self.from_var.get().strip()
|
||||||
|
if from_number == "+1XXXXXXXXXX":
|
||||||
|
from_number = ""
|
||||||
timestamp = datetime.now(timezone.utc).isoformat()
|
timestamp = datetime.now(timezone.utc).isoformat()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.log(f"Sending fax to {to_number}...")
|
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:
|
with open(pdf_path, "rb") as f:
|
||||||
resp = requests.post(
|
resp = requests.post(
|
||||||
f"{self._api_url()}/faxes",
|
f"{self._api_url()}/faxes",
|
||||||
auth=self._auth(),
|
auth=self._auth(),
|
||||||
files={"file": (pdf_path.name, f, "application/pdf")},
|
files={"file": (pdf_path.name, f, "application/pdf")},
|
||||||
data={
|
data=form_data,
|
||||||
"to": to_number,
|
|
||||||
"from": from_number,
|
|
||||||
},
|
|
||||||
timeout=60,
|
timeout=60,
|
||||||
)
|
)
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue