@@ -376,81 +376,72 @@ def get_forwarders(self):
376376 def create_forwarder (self , address , destination ):
377377 """Create an email forwarder"""
378378 try :
379- # Ensure we have just the username part
379+ # Ensure we have just the username part for the alias
380380 if '@' in address :
381381 username = address .split ('@' )[0 ]
382382 else :
383383 username = address
384384
385- # Various parameter formats DirectAdmin might expect
386- param_sets = [
387- # Format 1: Standard 【1】
388- {
389- 'domain' : self .domain ,
390- 'action' : 'create' ,
391- 'user' : username ,
392- 'email' : destination
393- },
394- # Format 2: With select0
395- {
396- 'domain' : self .domain ,
397- 'action' : 'create' ,
398- 'select0' : username ,
399- 'email' : destination
400- },
401- # Format 3: Forward specific
402- {
403- 'domain' : self .domain ,
404- 'action' : 'create' ,
405- 'forward' : f"{ username } ={ destination } "
406- }
407- ]
385+ # IMPORTANT FIX: Ensure destination is a full email address!
386+ if '@' not in destination :
387+ # If destination doesn't have @, assume it's a local user on the same domain
388+ destination = f"{ destination } @{ self .domain } "
408389
409390 print (f"\n === Creating Forwarder ===" )
410391 print (f"Username: { username } " )
411392 print (f"Domain: { self .domain } " )
412- print (f"Destination: { destination } " )
393+ print (f"Destination (full) : { destination } " ) # Show the full address
413394
414- response = None
415- for i , data in enumerate (param_sets ):
416- print (f"\n Trying parameter set { i + 1 } : { data } " )
395+ # Use the correct parameter format that DirectAdmin expects
396+ endpoint = '/CMD_API_EMAIL_FORWARDERS'
397+ data = {
398+ 'domain' : self .domain ,
399+ 'action' : 'create' ,
400+ 'user' : username ,
401+ 'email' : destination # This MUST be a full email address
402+ }
417403
418- endpoint = '/CMD_API_EMAIL_FORWARDERS'
419- response = self ._make_request (endpoint , data , method = 'POST' )
404+ print (f"Sending parameters: { data } " )
420405
421- if response :
422- print (f"Got response: { response } " )
423-
424- if isinstance (response , dict ):
425- # Check for errors
426- if 'error' in response :
427- error_msg = response .get ('error' , 'Unknown error' )
428- error_code = response .get ('error_code' , '' )
429- details = response .get ('details' , '' )
430- text = response .get ('text' , '' )
431-
432- # API error 1 often means permission or format issues 【2】
433- if error_msg == '1' or error_code == '1' :
434- print (f"API Error 1 detected. Details: { details } , Text: { text } " )
435- # Try next parameter set
436- continue
437- else :
438- return False , f"Error: { error_msg } { details } { text } " .strip ()
406+ response = self ._make_request (endpoint , data , method = 'POST' )
407+
408+ if response :
409+ print (f"Got response: { response } " )
410+
411+ if isinstance (response , dict ):
412+ # Check for errors
413+ if 'error' in response :
414+ error_msg = response .get ('error' , 'Unknown error' )
415+ details = response .get ('details' , '' )
416+ text = response .get ('text' , '' )
417+
418+ if details :
419+ # Parse URL-encoded details
420+ details = urllib .parse .unquote (details )
421+ if text :
422+ text = urllib .parse .unquote (text )
423+
424+ # Provide meaningful error message
425+ if 'invalid email' in details .lower ():
426+ return False , f"Invalid email address format: { details } "
427+ elif details or text :
428+ return False , f"{ text } : { details } " if text and details else (text or details )
429+ else :
430+ return False , f"Error: { error_msg } "
439431
440- # Check for success indicators
441- if any (key in response for key in ['success' , 'created' , 'added' ]):
442- return True , f"Forwarder { username } @{ self .domain } → { destination } created"
432+ # Check for success indicators
433+ if any (key in response for key in ['success' , 'created' , 'added' ]):
434+ return True , f"Forwarder { username } @{ self .domain } → { destination } created successfully "
443435
444- # If no error and no explicit success, might still be OK
445- if not any (key .startswith ('error' ) for key in response .keys ()):
446- return True , f"Forwarder { username } @{ self .domain } → { destination } created"
436+ # If no error and no explicit success, might still be OK
437+ if not any (key .startswith ('error' ) for key in response .keys ()):
438+ return True , f"Forwarder { username } @{ self .domain } → { destination } created"
447439
448- elif isinstance (response , str ):
449- if 'error' not in response .lower ():
450- return True , f"Forwarder { username } @{ self .domain } → { destination } created"
440+ elif isinstance (response , str ):
441+ if 'error' not in response .lower ():
442+ return True , f"Forwarder { username } @{ self .domain } → { destination } created"
451443
452- # If all parameter sets failed
453- return False , "Failed to create forwarder. Check DirectAdmin logs for details."
444+ return False , "Failed to create forwarder. No response from server."
454445
455446 except Exception as e :
456447 print (f"Error creating forwarder: { e } " )
0 commit comments